def initialize(self, V, Q, PS, D): super(Problem, self).initialize(V, Q, PS, D) print("IC type: " + self.ic) print("Velocity scale factor = %4.2f" % self.factor) reynolds = 728.761 * self.factor # TODO modify by nu_factor print("Computing with Re = %f" % reynolds) self.v_in = Function(V) print('Initializing error control') self.load_precomputed_bessel_functions(PS) self.solution = self.assemble_solution(0.0) # set constants for self.area = assemble(interpolate(Expression("1.0"), Q) * self.dsIn) # inflow area # womersley = steady + e^iCt, e^iCt has average 0 self.pg_normalization_factor.append(womersleyBC.average_analytic_pressure_grad(self.factor)) self.p_normalization_factor.append(norm( interpolate(womersleyBC.average_analytic_pressure_expr(self.factor), self.pSpace), norm_type='L2')) self.vel_normalization_factor.append(norm( interpolate(womersleyBC.average_analytic_velocity_expr(self.factor), self.vSpace), norm_type='L2')) # print('Normalisation factors (vel, p, pg):', self.vel_normalization_factor[0], self.p_normalization_factor[0], # self.pg_normalization_factor[0]) one = (interpolate(Expression('1.0'), Q)) self.outflow_area = assemble(one*self.dsOut) print('Outflow area:', self.outflow_area)
def update_time(self, actual_time, step_number): super(Problem, self).update_time(actual_time, step_number) if self.actual_time > 0.5 and int(round(self.actual_time * 1000)) % 1000 == 0: self.isWholeSecond = True seconds = int(round(self.actual_time)) self.second_list.append(seconds) self.N1 = seconds*self.stepsInSecond self.N0 = (seconds-1)*self.stepsInSecond else: self.isWholeSecond = False self.solution = self.assemble_solution(self.actual_time) # Update boundary condition self.tc.start('updateBC') self.v_in.assign(self.solution) self.tc.end('updateBC') # construct analytic pressure (used for computing pressure and force errors) self.tc.start('analyticP') analytic_pressure = womersleyBC.analytic_pressure(self.factor, self.actual_time) self.sol_p = interpolate(analytic_pressure, self.pSpace) self.tc.end('analyticP') self.tc.start('analyticVnorms') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt(assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) self.listDict['av_norm_L2']['list'].append(self.analytic_v_norm_L2) self.listDict['av_norm_H1']['list'].append(self.analytic_v_norm_H1) self.listDict['av_norm_H1w']['list'].append(self.analytic_v_norm_H1w) self.tc.end('analyticVnorms')
def permeability_tensor(self, K): FS = self.geometry.f0.function_space() TS = TensorFunctionSpace(self.geometry.mesh, 'P', 1) d = self.geometry.dim() fibers = Function(FS) fibers.vector()[:] = self.geometry.f0.vector().get_local() fibers.vector()[:] /= df.norm(self.geometry.f0) if self.geometry.s0 is not None: # normalize vectors sheet = Function(FS) sheet.vector()[:] = self.geometry.s0.vector().get_local() sheet.vector()[:] /= df.norm(self.geometry.s0) if d == 3: csheet = Function(FS) csheet.vector()[:] = self.geometry.n0.vector().get_local() csheet.vector()[:] /= df.norm(self.geometry.n0) else: return Constant(1) from ufl import diag factor = 10 if d == 3: ftensor = df.as_matrix(((fibers[0], sheet[0], csheet[0]), (fibers[1], sheet[1], csheet[1]), (fibers[2], sheet[2], csheet[2]))) ktensor = diag(df.as_vector([K, K / factor, K / factor])) else: ftensor = df.as_matrix( ((fibers[0], sheet[0]), (fibers[1], sheet[1]))) ktensor = diag(df.as_vector([K, K / factor])) permeability = df.project( df.dot(df.dot(ftensor, ktensor), df.inv(ftensor)), TS) return permeability
def update_time(self, actual_time, step_number): super(Problem, self).update_time(actual_time, step_number) if self.actual_time > 0.5 and abs( math.modf(actual_time)[0]) < 0.5 * self.metadata['dt']: self.second_list.append(int(round(self.actual_time))) self.solution = self.assemble_solution(self.actual_time) # Update boundary condition self.tc.start('updateBC') self.v_in.assign(self.onset_factor * self.solution) self.tc.end('updateBC') # construct analytic pressure (used for computing pressure and force errors) self.tc.start('analyticP') analytic_pressure = womersleyBC.analytic_pressure( self.factor, self.actual_time) self.sol_p = interpolate(analytic_pressure, self.pSpace) self.tc.end('analyticP') self.tc.start('analyticVnorms') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt( assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) self.listDict['av_norm_L2']['list'].append(self.analytic_v_norm_L2) self.listDict['av_norm_H1']['list'].append(self.analytic_v_norm_H1) self.listDict['av_norm_H1w']['list'].append(self.analytic_v_norm_H1w) self.tc.end('analyticVnorms')
def test_boussinesq_with_supg(): u1, _, theta1 = compute_boussinesq(target_time=1.0, lcar=0.1, supg=True) ref = 3.9591568082077104e-06 assert abs(norm(u1, 'L2') - ref) < 1.0e-6 * ref ref = 40.225818361936234 assert abs(norm(theta1, 'L2') - ref) < 1.0e-6 * ref return
def initialize(self, V, Q, PS, D): super(Problem, self).initialize(V, Q, PS, D) print("IC type: " + self.ic) print("Velocity scale factor = %4.2f" % self.factor) reynolds = 728.761 * self.factor print("Computing with Re = %f" % reynolds) # set constants for self.area = assemble(interpolate(Expression("1.0"), Q) * self.dsIn) # inflow area self.solution = interpolate(Expression(("0.0", "0.0", "factor*(1081.48-43.2592*(x[0]*x[0]+x[1]*x[1]))"), factor=self.factor), self.vSpace) analytic_pressure = womersleyBC.average_analytic_pressure_expr(self.factor) self.sol_p = interpolate(analytic_pressure, self.pSpace) self.analytic_gradient = womersleyBC.average_analytic_pressure_grad(self.factor) self.analytic_pressure_norm = norm(self.sol_p, norm_type='L2') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt(assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) print("Prepared analytic solution.") self.pg_normalization_factor.append(womersleyBC.average_analytic_pressure_grad(self.factor)) self.p_normalization_factor.append(self.analytic_pressure_norm) self.vel_normalization_factor.append(norm(self.solution, norm_type='L2')) print('Normalisation factors (vel, p, pg):', self.vel_normalization_factor[0], self.p_normalization_factor[0], self.pg_normalization_factor[0]) one = (interpolate(Expression('1.0'), Q)) self.outflow_area = assemble(one*self.dsOut) print('Outflow area:', self.outflow_area)
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_boussinesq(): u1, _, theta1 = compute_boussinesq(target_time=1.0, lcar=0.1, supg=False) ref = 3.959158183043053e-06 assert abs(norm(u1, 'L2') - ref) < 1.0e-6 * ref ref = 40.225818326711604 assert abs(norm(theta1, 'L2') - ref) < 1.0e-6 * ref return
def update_time(self, actual_time, step_number): super(Problem, self).update_time(actual_time, step_number) if self.actual_time > 0.5 and int(round(self.actual_time * 1000)) % 1000 == 0: self.isWholeSecond = True seconds = int(round(self.actual_time)) self.second_list.append(seconds) self.N1 = seconds*self.stepsInSecond self.N0 = (seconds-1)*self.stepsInSecond else: self.isWholeSecond = False # Update boundary condition self.tc.start('updateBC') if not self.ic == 'correct': self.v_in.t = self.actual_time self.tc.end('updateBC') self.tc.start('analyticVnorms') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt(assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) self.listDict['av_norm_L2']['list'].append(self.analytic_v_norm_L2) self.listDict['av_norm_H1']['list'].append(self.analytic_v_norm_H1) self.listDict['av_norm_H1w']['list'].append(self.analytic_v_norm_H1w) self.tc.end('analyticVnorms')
def compute_errors( self, dphi_k, phi_k ): # compute residual of solution at this iteration - assemble form into a vector F = d.assemble( self.weak_residual_form( phi_k ) ) # ... and compute norm. L2 is note yet implemented if self.norm_res=='L2': message = "UV_ERROR: L2 norm not implemented for residuals. Please use a different norm ('l2' or 'linf')" raise L2_Not_Implemented_For_F, message F_norm = d.norm( F, norm_type=self.norm_res ) # now compute norm of change in the solution # this nested if is to preserve the structure of the original built-in FEniCS norm function # within the modified rD_norm function if self.norm_change=='L2': # if you are here, you are computing the norm of a function object, as an integral # over the whole domain, and you need the r^2 factor in the measure (i.e. r^2 dr ) dphi_norm = rD_norm( dphi_k, self.physics.D, func_degree, norm_type=self.norm_change ) else: # if you are here, you are computing the norm of a vector. For this, the built-in norm function is # sufficient. The norm is either linf (max abs value at vertices) or l2 (Euclidean norm) dphi_norm = d.norm( dphi_k.vector(), norm_type=self.norm_change ) return dphi_norm, F_norm
def update_time(self, actual_time, step_number): super(Problem, self).update_time(actual_time, step_number) if self.actual_time > 0.5 and abs(math.modf(actual_time)[0]) < 0.5*self.metadata['dt']: self.second_list.append(int(round(self.actual_time))) self.solution = self.assemble_solution(self.actual_time) # Update boundary condition self.tc.start('updateBC') self.v_in.assign(self.onset_factor * self.solution) self.tc.end('updateBC') # construct analytic pressure (used for computing pressure and force errors) self.tc.start('analyticP') analytic_pressure = womersleyBC.analytic_pressure(self.factor, self.actual_time) self.sol_p = interpolate(analytic_pressure, self.pSpace) self.tc.end('analyticP') self.tc.start('analyticVnorms') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt(assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) self.listDict['av_norm_L2']['list'].append(self.analytic_v_norm_L2) self.listDict['av_norm_H1']['list'].append(self.analytic_v_norm_H1) self.listDict['av_norm_H1w']['list'].append(self.analytic_v_norm_H1w) self.tc.end('analyticVnorms')
def initialize(self, V, Q, PS, D): super(Problem, self).initialize(V, Q, PS, D) print("IC type: " + self.ic) print("Velocity scale factor = %4.2f" % self.factor) reynolds = 728.761 * self.factor # TODO modify by nu_factor print("Computing with Re = %f" % reynolds) # set constants for self.area = assemble(interpolate(Expression("1.0"), Q) * self.dsIn) # inflow area if self.doErrControl: self.solution = interpolate( Expression(("0.0", "0.0", "factor*(1081.48-43.2592*(x[0]*x[0]+x[1]*x[1]))"), factor=self.factor), self.vSpace) print("Prepared analytic solution.") # womersley = steady + e^iCt, e^iCt has average 0 self.pg_normalization_factor.append(womersleyBC.average_analytic_pressure_grad(self.factor)) self.p_normalization_factor.append(norm( interpolate(womersleyBC.average_analytic_pressure_expr(self.factor), self.pSpace), norm_type='L2')) self.vel_normalization_factor.append(norm( interpolate(womersleyBC.average_analytic_velocity_expr(self.factor), self.vSpace), norm_type='L2')) print('Normalisation factors (vel, p, pg):', self.vel_normalization_factor[0], self.p_normalization_factor[0], self.pg_normalization_factor[0])
def compute(self, get): u = get(self.valuename) if u is None: return None norm_type = self.params.norm_type if isinstance(u, Function): norm_type = norm_type if norm_type != "default" else "L2" return norm(u, norm_type) elif isinstance(u, Vector): norm_type = norm_type if norm_type != "default" else "l2" return norm(u, norm_type) else: if isinstance(u, (int, long, float)): u = [u] assert hasattr(u, "__len__") if self.params.norm_type == 'default': norm_type = 'l2' if self.params.norm_type == 'linf': return max([abs(_u) for _u in u]) else: # Extract norm type p = int(norm_type[1:]) return sum(abs(_u)**p for _u in u)**(1. / p)
def compute_norms(err, vector_norms=["l2", "linf"], function_norms=["L2", "H1"], show=True, tablefmt="simple", save=False): """ Compute norms, output to terminal, etc. """ info_split("Vector norms:", ", ".join(vector_norms)) info_split("Function norms:", ", ".join(function_norms)) headers = ["Fields"] + vector_norms + function_norms table = [] for field in err.keys(): row = [field] for norm_type in vector_norms: row.append(df.norm(err[field].vector(), norm_type=norm_type)) for norm_type in function_norms: row.append(df.norm(err[field], norm_type=norm_type)) table.append(row) from tabulate import tabulate tab_string = tabulate(table, headers, tablefmt=tablefmt, floatfmt="e") if show: info("\n" + tab_string + "\n") if save and rank == 0: info_split("Saving to file:", save) with open(save, "w") as outfile: outfile.write(tab_string)
def calc_err(f_num, f_ana, normtype='l2'): """ Calculate scaled L2 error """ f_err = dolfin.Function(f_num.function_space()) f_err.vector()[:] = f_ana.vector()[:] - f_num.vector()[:] if normtype == 'l2': return dolfin.norm(f_err) / dolfin.norm(f_ana) else: return dolfin.norm(f_err, normtype)
def targetmediumparameters(Vl, X, myplot=None): """ Arguments: Vl = function space X = x dimension of domain """ # medium parameters: H1, H2, H3, TT = 0.9, 0.1, 0.5, 0.25 CC = [2.5, 2.0, 2.0, 2.0] RR = [2.15, 2.1, 2.1, 2.1] #CC = [5.0, 2.0, 3.0, 4.0] #RR = [2.0, 2.1, 2.2, 2.5] LL, AA, BB = [], [], [] for cc, rr in zip(CC, RR): ll = rr * cc * cc LL.append(ll) AA.append(1. / ll) BB.append(1. / rr) # velocity is in [km/s] c = createparam(CC, Vl, X, H1, H2, H3, TT) if not myplot == None: myplot.set_varname('c_target') myplot.plot_vtk(c) # density is in [10^12 kg/km^3]=[g/cm^3] # assume rocks shale-sand-shale + salt inside small rectangle # see Marmousi2 print-out rho = createparam(RR, Vl, X, H1, H2, H3, TT) if not myplot == None: myplot.set_varname('rho_target') myplot.plot_vtk(rho) # bulk modulus is in [10^12 kg/km.s^2]=[GPa] lam = createparam(LL, Vl, X, H1, H2, H3, TT) if not myplot == None: myplot.set_varname('lambda_target') myplot.plot_vtk(lam) # af = createparam(AA, Vl, X, H1, H2, H3, TT) if not myplot == None: myplot.set_varname('alpha_target') myplot.plot_vtk(af) bf = createparam(BB, Vl, X, H1, H2, H3, TT) if not myplot == None: myplot.set_varname('beta_target') myplot.plot_vtk(bf) # Check: ones = dl.interpolate(dl.Constant('1.0'), Vl) check1 = af.vector() * lam.vector() erra = dl.norm(check1 - ones.vector()) assert erra < 1e-16 check2 = bf.vector() * rho.vector() errb = dl.norm(check2 - ones.vector()) assert errb < 1e-16 return af, bf, c, lam, rho
def test1(): # setup meshes P = 0.3 ref1 = 4 ref2 = 14 mesh1 = UnitSquare(2, 2) mesh2 = UnitSquare(2, 2) # refinement loops for level in range(ref1): mesh1 = refine(mesh1) for level in range(ref2): # mark and refine markers = CellFunction("bool", mesh2) markers.set_all(False) # randomly refine mesh for i in range(mesh2.num_cells()): if random() <= P: markers[i] = True mesh2 = refine(mesh2, markers) # create joint meshes mesh1j, parents1 = create_joint_mesh([mesh2], mesh1) mesh2j, parents2 = create_joint_mesh([mesh1], mesh2) # evaluate errors joint meshes ex1 = Expression("sin(2*A*x[0])*sin(2*A*x[1])", A=10) V1 = FunctionSpace(mesh1, "CG", 1) V2 = FunctionSpace(mesh2, "CG", 1) V1j = FunctionSpace(mesh1j, "CG", 1) V2j = FunctionSpace(mesh2j, "CG", 1) f1 = interpolate(ex1, V1) f2 = interpolate(ex1, V2) # interpolate on respective joint meshes f1j = interpolate(f1, V1j) f2j = interpolate(f2, V2j) f1j1 = interpolate(f1j, V1) f2j2 = interpolate(f2j, V2) # evaluate error with regard to original mesh e1 = Function(V1) e2 = Function(V2) e1.vector()[:] = f1.vector() - f1j1.vector() e2.vector()[:] = f2.vector() - f2j2.vector() print "error on V1:", norm(e1, "L2") print "error on V2:", norm(e2, "L2") plot(f1j, title="f1j") plot(f2j, title="f2j") plot(mesh1, title="mesh1") plot(mesh2, title="mesh2") plot(mesh1j, title="joint mesh from mesh1") plot(mesh2j, title="joint mesh from mesh2", interactive=True)
def compute_what(self, mhat): """ Compute update direction for what, given mhat """ self.wxhat.vector().zero() self.wxhat.vector().axpy( 1.0, self.invMwd * (self.Ax * mhat - self.gwx.vector())) normwxhat = norm(self.wxhat.vector()) self.wyhat.vector().zero() self.wyhat.vector().axpy( 1.0, self.invMwd * (self.Ay * mhat - self.gwy.vector())) normwyhat = norm(self.wyhat.vector()) if self.parameters['print']: print '[TVPD] |what|={}'.format( np.sqrt(normwxhat**2 + normwyhat**2))
def solve(self, problem, vector): res = vector.copy() problem.F(res, vector) nrm = norm(res) nrm0 = nrm k = 0 self._report(k, nrm, nrm0) while nrm > self.parameters['absolute_tolerance'] \ or nrm / nrm0 > self.parameters['relative_tolerance']: problem.F(res, vector) vector[:] += res nrm = norm(res) k += 1 self._report(k, nrm, nrm0) return
def targetmediumparameters(Vl, X, myplot=None): """ Arguments: Vl = function space X = x dimension of domain """ # medium parameters: size = 0.4 AA = [1.0, 1.4] BB = [1.0, 2.0] CC, LL, RR = [], [], [] for aa, bb in zip(AA, BB): cc = np.sqrt(bb / aa) rr = 1. / bb ll = 1. / aa CC.append(cc) RR.append(rr) LL.append(ll) c = createparam(CC, Vl, X, size) if not myplot == None: myplot.set_varname('c_target') myplot.plot_vtk(c) rho = createparam(RR, Vl, X, size) if not myplot == None: myplot.set_varname('rho_target') myplot.plot_vtk(rho) lam = createparam(LL, Vl, X, size) if not myplot == None: myplot.set_varname('lambda_target') myplot.plot_vtk(lam) at = createparam(AA, Vl, X, size) if not myplot == None: myplot.set_varname('alpha_target') myplot.plot_vtk(at) bt = createparam(BB, Vl, X, size) if not myplot == None: myplot.set_varname('beta_target') myplot.plot_vtk(bt) # Check: ones = dl.interpolate(dl.Constant('1.0'), Vl) check1 = at.vector() * lam.vector() erra = dl.norm(check1 - ones.vector()) assert erra < 1e-16, erra check2 = bt.vector() * rho.vector() errb = dl.norm(check2 - ones.vector()) assert errb < 1e-16, errb return at, bt, c, lam, rho
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 through metadata or function of mesh) self.tc.end('computePG') self.tc.start('analyticP') analytic_gradient = womersleyBC.analytic_pressure_grad(self.factor, self.actual_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)) 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 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 compute_div(self, is_tent, velocity): self.tc.start('divNorm') div_list = self.listDict['d2' if is_tent else 'd']['list'] div_list.append(norm(velocity, 'Hdiv0')) if self.isWholeSecond: self.listDict['d2' if is_tent else 'd']['slist'].append( sum([i*i for i in div_list[self.N0:self.N1]])/self.stepsInSecond) self.tc.end('divNorm')
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 testsplitassign(): USEi = True mesh = dl.UnitSquareMesh(40, 40) V1 = dl.FunctionSpace(mesh, "Lagrange", 2) V2 = dl.FunctionSpace(mesh, "Lagrange", 2) if USEi: V1V2 = createMixedFSi([V1, V2]) splitassign = SplitAndAssigni([V1, V2], mesh.mpi_comm()) else: V1V2 = createMixedFS(V1, V2) splitassign = SplitAndAssign(V1, V2, mesh.mpi_comm()) mpirank = dl.MPI.rank(mesh.mpi_comm()) u = dl.interpolate(dl.Expression(("x[0]*x[1]", "11+x[0]+x[1]"), degree=10), V1V2) uu = dl.Function(V1V2) u1, u2 = u.split(deepcopy=True) u1v, u2v = splitassign.split(u.vector()) u11 = dl.interpolate(dl.Expression("x[0]*x[1]", degree=10), V1) u22 = dl.interpolate(dl.Expression("11+x[0]+x[1]", degree=10), V2) a,b,c,d= dl.norm(u1.vector()-u1v), dl.norm(u2.vector()-u2v),\ dl.norm(u1.vector()-u11.vector()), dl.norm(u2.vector()-u22.vector()) if mpirank == 0: print '\nSplitting an interpolated function:', a, b, c, d if USEi: uv = splitassign.assign([u1v, u2v]) else: uv = splitassign.assign(u1v, u2v) dl.assign(uu.sub(0), u11) dl.assign(uu.sub(1), u22) a, b = dl.norm(uv - u.vector()), dl.norm(uv - uu.vector()) if mpirank == 0: print 'Putting it back together:', a, b for ii in xrange(10): u.vector()[:] = np.random.randn(len(u.vector().array())) u1, u2 = u.split(deepcopy=True) u1v, u2v = splitassign.split(u.vector()) if USEi: uv = splitassign.assign([u1v, u2v]) else: uv = splitassign.assign(u1v, u2v) a, b = dl.norm(u1.vector() - u1v), dl.norm(u2.vector() - u2v) c = dl.norm(uv - u.vector()) if mpirank == 0: print 'Splitting random numbers:', a, b print 'Putting it back together:', c
def test_residual(problem): mesh_size = 16 mesh_generator, _, f, _ = problem() mesh, dx, _ = mesh_generator(mesh_size) # from dolfin import plot, interactive # plot(mesh) # interactive() V = FunctionSpace(mesh, "CG", 1) Mu = {0: 1.0} Sigma = {0: 1.0} omega = 1.0 convections = {} rhs = {0: f["value"]} # solve equation system phi_list = maxwell.solve( V, dx, Mu=Mu, Sigma=Sigma, omega=omega, f_list=[rhs], f_degree=f["degree"], convections=convections, tol=1.0e-15, bcs=None, verbose=False, ) phi = phi_list[0] # build residuals Res_r, Res_i, Rhs_r, Rhs_i = _build_residuals(V, dx, phi, omega, Mu, Sigma, convections, rhs, f["degree"]) # Assert that the norm of the residual is smaller than a tolerance times # the norm of the right-hand side. This is a typical Krylov criterion. nrm_rhs = sqrt(norm(Rhs_r)**2 + norm(Rhs_i)**2) nrm_res = sqrt(norm(Res_r)**2 + norm(Res_i)**2) assert nrm_res < 1.0e-13 * nrm_rhs return
def grad(self, m): """ compute the gradient at m """ setfct(self.m, m) self._assemble_invMw() self.gwx.vector().zero() self.gwx.vector().axpy(1.0, assemble(self.misfitwx)) normgwx = norm(self.gwx.vector()) self.gwy.vector().zero() self.gwy.vector().axpy(1.0, assemble(self.misfitwy)) normgwy = norm(self.gwy.vector()) if self.parameters['print']: print '[TVPD] |gw|={}'.format(np.sqrt(normgwx**2 + normgwy**2)) return self.Htvx*(self.wx.vector() - self.invMwd*self.gwx.vector()) \ + self.Htvy*(self.wy.vector() - self.invMwd*self.gwy.vector())
def targetmediumparameters(Vl, X, myplot=None): """ Arguments: Vl = function space X = x dimension of domain """ # velocity is in [km/s] c = createparam(Vl, DD, CC[0], CC[1], CC[2]) if not myplot == None: myplot.set_varname('c_target') myplot.plot_vtk(c) # density is in [10^12 kg/km^3]=[g/cm^3] # assume rocks shale-sand-shale + salt inside small rectangle # see Marmousi2 print-out rho = createparam(Vl, DD, RR[0], RR[1], RR[2]) if not myplot == None: myplot.set_varname('rho_target') myplot.plot_vtk(rho) # bulk modulus is in [10^12 kg/km.s^2]=[GPa] lam = createparam(Vl, DD, LL[0], LL[1], LL[2]) if not myplot == None: myplot.set_varname('lambda_target') myplot.plot_vtk(lam) # af = createparam(Vl, DD, AA[0], AA[1], AA[2]) if not myplot == None: myplot.set_varname('alpha_target') myplot.plot_vtk(af) bf = createparam(Vl, DD, BB[0], BB[1], BB[2]) if not myplot == None: myplot.set_varname('beta_target') myplot.plot_vtk(bf) # Check: ones = dl.interpolate(dl.Constant('1.0'), Vl) check1 = af.vector() * lam.vector() erra = dl.norm(check1 - ones.vector()) assert erra < 1e-16 check2 = bf.vector() * rho.vector() errb = dl.norm(check2 - ones.vector()) assert errb < 1e-16 return af, bf, c, lam, rho
def initialize(self, V, Q, PS, D): super(Problem, self).initialize(V, Q, PS, D) print("IC type: " + self.ic) print("Velocity scale factor = %4.2f" % self.factor) reynolds = 728.761 * self.factor print("Computing with Re = %f" % reynolds) # set constants for self.area = assemble(interpolate(Expression("1.0"), Q) * self.dsIn) # inflow area self.solution = interpolate( Expression(("0.0", "0.0", "factor*(1081.48-43.2592*(x[0]*x[0]+x[1]*x[1]))"), factor=self.factor), self.vSpace) analytic_pressure = womersleyBC.average_analytic_pressure_expr( self.factor) self.sol_p = interpolate(analytic_pressure, self.pSpace) self.analytic_gradient = womersleyBC.average_analytic_pressure_grad( self.factor) self.analytic_pressure_norm = norm(self.sol_p, norm_type='L2') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt( assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) print("Prepared analytic solution.") self.pg_normalization_factor.append( womersleyBC.average_analytic_pressure_grad(self.factor)) self.p_normalization_factor.append(self.analytic_pressure_norm) self.vel_normalization_factor.append( norm(self.solution, norm_type='L2')) print('Normalisation factors (vel, p, pg):', self.vel_normalization_factor[0], self.p_normalization_factor[0], self.pg_normalization_factor[0]) one = (interpolate(Expression('1.0'), Q)) self.outflow_area = assemble(one * self.dsOut) print('Outflow area:', self.outflow_area)
def get_umax(u): # Compute the maximum velocity. # First get a vector with the squared norms, then get the maximum value of # it. This assumes that the maximum is attained in a node, and that the # vectors express the value in certain control points (nodes, edge # midpoints etc.). usplit = u.split(deepcopy=True) vec = usplit[0].vector() * usplit[0].vector() for k in range(1, len(u)): vec += usplit[k].vector() * usplit[k].vector() return numpy.sqrt(norm(vec, "linf"))
def error_norm(vec1, vec2, normstr="L2"): e = 0.0 if isinstance(vec1, MultiVector): assert isinstance(vec2, MultiVector) assert vec1.active_indices() == vec2.active_indices() for mi in vec1.keys(): V = vec1[mi]._fefunc.function_space() errfunc = Function(V, vec1[mi]._fefunc.vector() - vec2[mi]._fefunc.vector()) if isinstance(normstr, str): e += norm(errfunc, normstr) ** 2 else: e += normstr(errfunc) ** 2 return sqrt(e) else: V = vec1.function_space() errfunc = Function(V, vec1.vector() - vec2.vector()) if isinstance(normstr, str): return norm(errfunc, normstr) else: return normstr(errfunc)
def compute_errors( self, du_k, u_k ): r""" Computes measures of error at a given iteration. With reference to Eq. :eq:`Eq_residual_criterion` and Eq. :eq:`Eq_change_criterion`, this function computes the norm of the residual :math:`|| \mathcal{F}[u^{(k)}] ||` and the norm of the change in the solution :math:`|| u^{(k)}-u^{(k-1)} ||` at one given iteration. *Parameters* du_k difference in the solution over the whole domain at this iteration. u_k solution at this iteration, for the computation of the residual :math:`||F(u_k)||` """ # compute residual of solution at this iteration - assemble form into a vector F = d.assemble( self.weak_residual_form( u_k ) ) # ... and compute norm. L2 is note yet implemented if self.norm_res=='L2': message = "L2 norm not implemented for residuals. Please use a different norm ('l2' or 'linf')" raise NotImplementedError(message) # the built-in norm function is fine because it's computing the linf or Euclidean norm here F_norm = d.norm( F, norm_type=self.norm_res ) # now compute norm of change in the solution # this nested if is to preserve the structure of the original built-in FEniCS norm function # within the modified r2_norm function if self.norm_change=='L2': # if you are here, you are computing the norm of a function object, as an integral # over the whole domain, and you need the r^2 factor in the measure (i.e. r^2 dr ) du_norm = r2_norm( du_k, self.fem.func_degree, norm_type=self.norm_change ) else: # if you are here, you are computing the norm of a vector. For this, the built-in norm function is # sufficient. The norm is either linf (max abs value at vertices) or l2 (Euclidean norm) du_norm = d.norm( du_k.vector(), norm_type=self.norm_change ) return du_norm, F_norm
def eigenvalue_residual_norm(self, norm_type='l2'): r = PETScVector() y = PETScVector() self.B.mult(self.sln_vec, r) self.A.mult(self.sln_vec, y) r.apply("insert") y.apply("insert") r -= self.keff * y return norm(r, norm_type)
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 __init__(self, meth, Vm, mtrue, maxnbLS=15): self.meth = meth if self.meth == 'Newt': self.Newt = True else: self.Newt = False self.Vm = Vm self.mtrue = interpolate(mtrue, self.Vm) self.diff = Function(self.Vm) self.normmtrue = norm(self.mtrue) # Note: this is a global value self.maxnbLS = maxnbLS self._createoutputlines() self.index = 0 self.gradnorminit = None self.printrank = 0
def comp_cont_error(v, fpbc, Q): """Compute the L2 norm of the residual of the continuity equation Bv = g """ q = TrialFunction(Q) divv = assemble(q*div(v)*dx) conRhs = Function(Q) conRhs.vector().set_local(fpbc) ContEr = norm(conRhs.vector() - divv) return ContEr
def __abs__(self): """ Overloading the abs operator for mesh types Returns: float: absolute maximum of all mesh values """ # take absolute values of the mesh values absval = df.norm(self.values, 'L2') # return maximum return absval
def __abs__(self): """ Overloading the abs operator for mesh types Returns: absolute maximum of all mesh values """ # take absolute values of the mesh values absval = df.norm(self.values,'L2') # return maximum return absval
def compile_continuation_data(self, load, iteration, perturbed): model = self.model u = self.solver.u alpha = self.solver.alpha if not perturbed: self.continuation_data_i = {} self.continuation_data_i["elastic_energy"] = assemble( model.elastic_energy_density(model.eps(u), alpha) * model.dx) if self.user_density is not None: self.continuation_data_i["elastic_energy"] += assemble( self.user_density * model.dx) self.continuation_data_i["dissipated_energy"] = assemble( model.damage_dissipation_density(alpha) * model.dx) self.continuation_data_i[ "total_energy"] = self.continuation_data_i[ "elastic_energy"] + self.continuation_data_i[ "dissipated_energy"] self.continuation_data_i["load"] = load self.continuation_data_i["iteration"] = iteration self.continuation_data_i["alpha_l2"] = alpha.vector().norm('l2') self.continuation_data_i["alpha_h1"] = norm(alpha, 'h1') self.continuation_data_i["alpha_max"] = np.max(alpha.vector()[:]) self.continuation_data_i["eigs"] = self.stability.eigs else: elastic_post = assemble( model.elastic_energy_density(model.eps(u), alpha) * model.dx) if self.user_density is not None: elastic_post += assemble(self.user_density * model.dx) dissipated_post = assemble( model.damage_dissipation_density(alpha) * model.dx) self.continuation_data_i[ "elastic_energy_diff"] = elastic_post - self.continuation_data_i[ "elastic_energy"] self.continuation_data_i[ "dissipated_energy_diff"] = dissipated_post - self.continuation_data_i[ "dissipated_energy"] self.continuation_data_i["total_energy_diff"] = self.continuation_data_i["elastic_energy_diff"]\ +self.continuation_data_i["dissipated_energy_diff"] # ColorPrint.print_info('energy {:4e}'.format(elastic_energy_post + dissipated_energy_post)) # ColorPrint.print_info('estimate {:4e}'.format(stability.en_estimate)) # ColorPrint.print_info('en-est {:4e}'.format(elastic_energy_post + dissipated_energy_post-stability.en_estimate)) pass
def test_bndModel(): Lx, Ly, Nx, Ny, NxyMicro = 2.0, 0.5, 12, 4, 50 singleScaleFile = resultFolder + "bar_single_scale.xdmf" multiScaleFile = resultFolder + "bar_multiscale_standalone_%s.xdmf" start = timer() print("simulating single scale") os.system("python bar_single_scale.py %d %d" % (Nx, Ny)) end = timer() print('finished in ', end - start) for bndModel in ['per', 'lin', 'MR', 'lag']: suffix = "{0} {1} {2} {3} > log_{3}.txt".format( Nx, Ny, NxyMicro, bndModel) start = timer() print("simulating using " + bndModel) os.system("python bar_multiscale_standalone.py " + suffix) end = timer() print('finished in ', end - start) mesh = df.RectangleMesh(df.Point(0.0, 0.0), df.Point(Lx, Ly), Nx, Ny, "right/left") Uh = df.VectorFunctionSpace(mesh, "Lagrange", 1) uh0 = df.Function(Uh) with df.XDMFFile(resultFolder + "bar_single_scale.xdmf") as f: f.read_checkpoint(uh0, 'u') error = {} ehtemp = df.Function(Uh) for bndModel in ['per', 'lin', 'MR', 'lag']: with df.XDMFFile(multiScaleFile % bndModel) as f: f.read_checkpoint(ehtemp, 'u') ehtemp.vector().set_local(ehtemp.vector().get_local()[:] - uh0.vector().get_local()[:]) error[bndModel] = df.norm(ehtemp) print(error[bndModel]) assert np.abs(error['lin'] - error['lag']) < 1e-12 assert np.abs(error['per'] - 0.006319071443377064) < 1e-12 assert np.abs(error['lin'] - 0.007901978018038507) < 1e-12 assert np.abs(error['MR'] - 0.0011744201374588351) < 1e-12
def initialize(self, V, Q, PS, D): super(Problem, self).initialize(V, Q, PS, D) print("IC type: " + self.ic) print("Velocity scale factor = %4.2f" % self.factor) reynolds = 728.761 * self.factor / self.args.nufactor print("Computing with Re = %f" % reynolds) self.v_in = Function(V) print('Initializing error control') self.load_precomputed_bessel_functions(PS) self.solution = self.assemble_solution(0.0) # set constants for self.area = assemble( interpolate(Expression("1.0", degree=1), Q) * self.dsIn) # inflow area # womersley = steady + e^iCt, e^iCt has average 0 self.pg_normalization_factor.append( womersleyBC.average_analytic_pressure_grad(self.factor)) self.p_normalization_factor.append( norm(interpolate( womersleyBC.average_analytic_pressure_expr(self.factor), self.pSpace), norm_type='L2')) self.vel_normalization_factor.append( norm(interpolate( womersleyBC.average_analytic_velocity_expr(self.factor), self.vSpace), norm_type='L2')) one = (interpolate(Expression('1.0', degree=1), Q)) self.outflow_area = assemble(one * self.dsOut) print('Outflow area:', self.outflow_area)
def test_iterate_gamma(problem): target_gamma = 0.1 gamma = problem.material.activation if has_dolfin_adjoint: dolfin.parameters["adjoint"]["stop_annotating"] = False dolfin_adjoint.adj_reset() iterate(problem, gamma, target_gamma) assert all(gamma.vector().get_local() == target_gamma) assert dolfin.norm(problem.state.vector()) > 0 if has_dolfin_adjoint: assert dolfin_adjoint.replay_dolfin(tol=1e-12)
def rayleigh_quotient(self, vec, A=None, B=None): if A is None: A = self.A_fine B = self.B_fine r = PETScVector() A.mult(vec, r) nom = MPI_sum( numpy.dot(r, vec) ) if B.size(0) > 0: B.mult(vec, r) denom = MPI_sum( numpy.dot(r, vec) ) else: denom = sqr(norm(r, norm_type='l2')) return nom/denom
def test_parallel(): Lx, Ly, Ny, Nx, NxyMicro = 0.5, 2.0, 12, 5, 50 bndModel = 'per' suffix = "%d %d %d %s > log_%s.txt" % (Nx, Ny, NxyMicro, bndModel, bndModel) start = timer() print("simulating single core") os.system("python bar_multiscale_standalone.py " + suffix) end = timer() print('finished in ', end - start) for nProc in [1, 2, 3, 4]: start = timer() print("simulating using nProc", nProc) os.system("mpirun -n %d python bar_multiscale_parallel.py " % nProc + suffix) end = timer() print('finished in ', end - start) mesh = df.RectangleMesh(df.Point(0.0, 0.0), df.Point(Lx, Ly), Nx, Ny, "right/left") Uh = df.VectorFunctionSpace(mesh, "Lagrange", 1) uh0 = df.Function(Uh) with df.XDMFFile("bar_multiscale_standalone_%s.xdmf" % bndModel) as f: f.read_checkpoint(uh0, 'u') error = {} ehtemp = df.Function(Uh) for nProc in [1, 2, 3, 4]: with df.XDMFFile("bar_multiscale_parallel_%s_np%d.xdmf" % (bndModel, nProc)) as f: f.read_checkpoint(ehtemp, 'u') ehtemp.vector().set_local(ehtemp.vector().get_local()[:] - uh0.vector().get_local()[:]) error[nProc] = df.norm(ehtemp) assert np.max(np.array(list(error.values()))) < 1e-13
def residual_norm(self, vec, lam, norm_type='l2', A=None, B=None): if A is None: A = self.A_fine B = self.B_fine r = PETScVector() A.mult(vec, r) if B.size(0) > 0: y = PETScVector() B.mult(vec, y) else: y = 1 r -= lam*y return norm(r,norm_type)
def compute(self, get): u = get(self.valuename1) uh = get(self.valuename2) if u is None: return None if isinstance(uh, Function): norm_type = self.params.norm_type if self.params.norm_type != "default" else "L2" err = errornorm(u, uh, norm_type=norm_type, degree_rise=self.params.degree_rise) if self.params.relative: return err/(norm(u, norm_type=norm_type)+DOLFIN_EPS) else: return err else: if isinstance(u, (int, long, float)): u = [u] if isinstance(uh, (int, long, float)): uh = [uh] assert hasattr(u, "__len__") assert hasattr(uh, "__len__") assert len(u) == len(uh) if self.params.norm_type == 'default': norm_type = 'l2' else: norm_type = self.params.norm_type if norm_type == 'linf': err = max([abs(_u-_uh) for _u,_uh in zip(u,uh)]) if self.params.relative: return err/(max([abs(_u) for _u in u])+DOLFIN_EPS) else: return err else: # Extract norm type p = int(norm_type[1:]) err = sum(abs(_u-_uh)**p for _u, _uh in zip(u,uh))**(1./p) if self.params.relative: return err/(sum(abs(_u)**p for _u in u)**(1./p)+DOLFIN_EPS) else: return err
def solve(self, max_it, res_norm_tol, smoothing_steps=None, norm_type='l2'): self.num_it_coarse = 0 self.num_it_fine = 0 if smoothing_steps is None: smoothing_steps = self.problem.beta/2+1 for i in xrange(max_it): if self.verbosity >= 1: print0(pid+"Iteration {}".format(i)) self.update_coarse_level() self.solve_on_coarse_level() self.prolongate() self.smooth_on_fine_level(smoothing_steps) self.vec_fine *= 1./norm(self.vec_fine, norm_type) if self.problem.residual_norm(norm_type) <= res_norm_tol: self.num_it = i+1 break self.lam = self.problem.rayleigh_quotient(self.vec_fine) self.num_it_fine_smoothing = self.num_it * smoothing_steps
def compute_div(self, is_tent, velocity): self.tc.start('divNorm') div_list = self.listDict['d2' if is_tent else 'd']['list'] div_list.append(norm(velocity, 'Hdiv0')) self.tc.end('divNorm')
def evaluateLocalProjectionError(cls, w, mu, m, coeff_field, pde, Lambda, maxh=0.0, local=True, projection_degree_increase=1, refine_mesh=1): """Evaluate the local projection error according to EGSZ (6.4). Localisation of the global projection error (4.8) by (6.4) ..math:: \zeta_{\mu,T,m}^{\mu\pm e_m} := ||a_m/\overline{a}||_{L^\infty(D)} \alpha_{\mu_m\pm 1}\int_T | \nabla( \Pi_{\mu\pm e_m}^\mu(\Pi_\mu^{\mu\pm e_m} w_{N,mu\pm e_)m})) - w_{N,mu\pm e_)m} |^2\;dx The sum :math:`\zeta_{\mu,T,m}^{\mu+e_m} + \zeta_{\mu,T,m}^{\mu-e_m}` is returned. """ # determine ||a_m/\overline{a}||_{L\infty(D)} (approximately) a0_f = coeff_field.mean_func am_f, _ = coeff_field[m] if isinstance(a0_f, tuple): assert isinstance(am_f, tuple) a0_f = a0_f[0] am_f = am_f[0] # create discretisation space V_coeff, _, _, _ = w[mu].basis.refine_maxh(maxh) # interpolate coefficient functions on mesh f_coeff = V_coeff.new_vector(sub_spaces=0) # print "evaluateLocalProjectionError" # print f_coeff.num_sub_spaces # print a0_f.value_shape() f_coeff.interpolate(a0_f) amin = f_coeff.min_val f_coeff.interpolate(am_f) ammax = f_coeff.max_val ainfty = ammax / amin assert isinstance(ainfty, float) logger.debug("==== local projection error for mu = %s ====", mu) logger.debug("amin = %f amax = %f ainfty = %f", amin, ammax, ainfty) # prepare polynom coefficients _, am_rv = coeff_field[m] beta = am_rv.orth_polys.get_beta(mu[m]) # mu+1 mu1 = mu.inc(m) if mu1 in Lambda: logger.debug("[LPE-A] local projection error for mu = %s with %s", mu, mu1) # debug--- # if True: # from dolfin import Function, inner # V1 = w[mu]._fefunc.function_space(); # ufl = V1.ufl_element(); # V2 = FunctionSpace(V1.mesh(), ufl.family(), ufl.degree() + 1) # f1 = Function(V1) # f1.interpolate(w[mu1]._fefunc) # f12 = Function(V2) # f12.interpolate(f1) # f2 = Function(V2) # f2.interpolate(w[mu1]._fefunc) # err2 = Function(V2, f2.vector() - f12.vector()) # aerr = a0_f * inner(nabla_grad(err2), nabla_grad(err2)) * dx # perr = sqrt(assemble(aerr)) # logger.info("DEBUG A --- global projection error %s - %s: %s", mu1, mu, perr) # ---debug # evaluate H1 semi-norm of projection error error1, sum_up = w.get_projection_error_function(mu1, mu, 1 + projection_degree_increase, refine_mesh=refine_mesh) logger.debug("global projection error norms: L2 = %s and H1 = %s", norm(error1._fefunc, "L2"), norm(error1._fefunc, "H1")) # pe = weighted_H1_norm(a0_f, error1, local) # TODO: this should be the energy error! # pe = sum_up(pe) # summation for cells according to reference mesh refinement if local: energynorm = pde.get_energy_norm(mesh=error1._fefunc.function_space().mesh()) pe = energynorm(error1._fefunc) pe = np.array([e ** 2 for e in pe]) # square norms pe = sum_up(pe) # summation for cells according to reference mesh refinement pe = np.sqrt(pe) # take square root again for summed norm logger.debug("summed local projection errors: %s", sqrt(sum([e ** 2 for e in pe]))) # # DEBUG--- # pe2 = weighted_H1_norm(a0_f, error1, local) # TODO: this should be the energy error! # pe2 = np.array([e ** 2 for e in pe2]) # square norms # pe2 = sum_up(pe2) # summation for cells according to reference mesh refinement # pe2 = np.sqrt(pe2) # take square root again for summed norm # logger.warn("[A] summed local projection errors: %s = %s \t weights: %s = %s", sqrt(sum([e ** 2 for e in pe])), sqrt(sum([e2 ** 2 for e2 in pe2])), a0_f((0, 0)), pde._a0((0, 0))) # # ---DEBUG else: pe = pde.energy_norm(error1._fefunc) logger.debug("global projection error: %s", pe) zeta1 = beta[1] * pe else: if local: zeta1 = np.zeros(w[mu].basis.mesh.num_cells()) else: zeta1 = 0 # mu -1 mu2 = mu.dec(m) if mu2 in Lambda: logger.debug("[LPE-B] local projection error for mu = %s with %s", mu, mu2) # debug--- # if True: # from dolfin import Function, inner # V1 = w[mu]._fefunc.function_space(); # ufl = V1.ufl_element(); # V2 = FunctionSpace(V1.mesh(), ufl.family(), ufl.degree() + 1) # f1 = Function(V1) # f1.interpolate(w[mu2]._fefunc) # f12 = Function(V2) # f12.interpolate(f1) # f2 = Function(V2) # f2.interpolate(w[mu2]._fefunc) # err2 = Function(V2, f2.vector() - f12.vector()) # aerr = a0_f * inner(nabla_grad(err2), nabla_grad(err2)) * dx # perr = sqrt(assemble(aerr)) # logger.info("DEBUG B --- global projection error %s - %s: %s", mu2, mu, perr) # ---debug # evaluate H1 semi-norm of projection error error2, sum_up = w.get_projection_error_function(mu2, mu, 1 + projection_degree_increase, refine_mesh=refine_mesh) logger.debug("global projection error norms: L2 = %s and H1 = %s", norm(error2._fefunc, "L2"), norm(error2._fefunc, "H1")) # pe = weighted_H1_norm(a0_f, error2, local) # TODO: this should be the energy error! # pe = sum_up(pe) # summation for cells according to reference mesh refinement if local: energynorm = pde.get_energy_norm(mesh=error2._fefunc.function_space().mesh()) pe = energynorm(error2._fefunc) pe = np.array([e ** 2 for e in pe]) # square norms pe = sum_up(pe) # summation for cells according to reference mesh refinement pe = np.sqrt(pe) # take square root again for summed norm logger.debug("summed local projection errors: %s", sqrt(sum([e ** 2 for e in pe]))) # # DEBUG--- # from dolfin import plot ## plot(w[mu]._fefunc) ## plot(error2._fefunc, interactive=True) # pe2 = weighted_H1_norm(a0_f, error2, local) # TODO: this should be the energy error! # pe2 = np.array([e ** 2 for e in pe2]) # square norms # pe2 = sum_up(pe2) # summation for cells according to reference mesh refinement # pe2 = np.sqrt(pe2) # take square root again for summed norm # logger.warn("[B] summed local projection errors: %s = %s \t weights: %s = %s", sqrt(sum([e ** 2 for e in pe])), sqrt(sum([e2 ** 2 for e2 in pe2])), a0_f((0, 0)), pde._a0((0, 0))) # # ---DEBUG else: pe = pde.energy_norm(error2._fefunc) logger.debug("global projection error: %s", pe) zeta2 = beta[-1] * pe else: if local: zeta2 = np.zeros(w[mu].basis.mesh.num_cells()) else: zeta2 = 0 logger.debug("beta[-1] = %s beta[1] = %s ainfty = %s", beta[-1], beta[1], ainfty) zeta = ainfty * (zeta1 + zeta2) return zeta
'u_tent_plot': Function(Vplot), 'u_last_plot': Function(Vplot)} state_NR = {'name': 'NR', 'u_prev': Function(V), 'u_tent': Function(V), 'u_last': Function(V), 'pressure': Function(Q), 'p_tent': Function(Q), 'rot': True, 'null': True, 'u_tent_plot': Function(Vplot), 'u_last_plot': Function(Vplot)} # states = [state_B_, state_BR, state_N_, state_NR] states = [state_B_] t = timestep step = 1 while t < time + 1e-6: print('t = ', t) v_in_expr.t = t for state in states: solve_cycle(state) n = norm(state['u_last']) print(n) plot_state(state, t) interactive() if math.isnan(n): exit('Failed') if n > 5 * v_in * length: exit('Norm too big!') t += timestep step += 1
def fixed_source_residual_norm(self, norm_type='l2'): y = PETScVector() self.A.mult(self.sln_vec, y) y.apply("insert") return norm(self.Q - y, norm_type)
def solve_maxwell(V, dx, Mu, Sigma, # dictionaries omega, f_list, # list of dictionaries convections, # dictionary bcs=None, tol=1.0e-12, compute_residuals=True, verbose=False ): '''Solve the complex-valued time-harmonic Maxwell system in 2D cylindrical coordinates. :param V: function space for potentials :param dx: measure :param omega: current frequency :type omega: float :param f_list: list of right-hand sides :param convections: convection terms by subdomains :type convections: dictionary :param bcs: Dirichlet boundary conditions :param tol: solver tolerance :type tol: float :param verbose: solver verbosity :type verbose: boolean :rtype: list of functions ''' # For the exact solution of the magnetic scalar potential, see # <http://www.physics.udel.edu/~jim/PHYS809_10F/Class_Notes/Class_26.pdf>. # Here, the value of \phi along the rotational axis is specified as # # phi(z) = 2 pi I / c * (z/|z| - z/sqrt(z^2 + a^2)) # # where 'a' is the radius of the coil. This expression contradicts what is # specified by [Chaboudez97]_ who claim that phi=0 is the natural value # at the symmetry axis. # # For more analytic expressions, see # # Simple Analytic Expressions for the Magnetic Field of a Circular # Current Loop; # James Simpson, John Lane, Christopher Immer, and Robert Youngquist; # <http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20010038494_2001057024.pdf>. # # Check if boundary conditions on phi are explicitly provided. if not bcs: # Create Dirichlet boundary conditions. # In the cylindrically symmetric formulation, the magnetic vector # potential is given by # # A = e^{i omega t} phi(r,z) e_{theta}. # # It is natural to demand phi=0 along the symmetry axis r=0 to avoid # discontinuities there. # Also, this makes sure that the system is well-defined (see comment # below). # def xzero(x, on_boundary): return on_boundary and abs(x[0]) < DOLFIN_EPS bcs = DirichletBC(V * V, (0.0, 0.0), xzero) # # Concerning the boundary conditions for the rest of the system: # At the other boundaries, it is not uncommon (?) to set so-called # impedance boundary conditions; see, e.g., # # Chaboudez et al., # Numerical Modeling in Induction Heating for Axisymmetric # Geometries, # IEEE Transactions on Magnetics, vol. 33, no. 1, Jan 1997, # <http://www.esi-group.com/products/casting/publications/Articles_PDF/InductionaxiIEEE97.pdf>. # # or # # <ftp://ftp.math.ethz.ch/pub/sam-reports/reports/reports2010/2010-39.pdf>. # # TODO review those, references don't seem to be too accurate # Those translate into Robin-type boundary conditions (and are in fact # sometimes called that, cf. # https://en.wikipedia.org/wiki/Robin_boundary_condition). # The classical reference is # # Impedance boundary conditions for imperfectly conducting # surfaces, # T.B.A. Senior, # <http://link.springer.com/content/pdf/10.1007/BF02920074>. # #class OuterBoundary(SubDomain): # def inside(self, x, on_boundary): # return on_boundary and abs(x[0]) > DOLFIN_EPS #boundaries = FacetFunction('size_t', mesh) #boundaries.set_all(0) #outer_boundary = OuterBoundary() #outer_boundary.mark(boundaries, 1) #ds = Measure('ds')[boundaries] ##n = FacetNormal(mesh) ##a += - 1.0/Mu[i] * dot(grad(r*ur), n) * vr * ds(1) \ ## - 1.0/Mu[i] * dot(grad(r*ui), n) * vi * ds(1) ##L += - 1.0/Mu[i] * 1.0 * vr * ds(1) \ ## - 1.0/Mu[i] * 1.0 * vi * ds(1) ## This is -n.grad(r u) = u: #a += 1.0/Mu[i] * ur * vr * ds(1) \ # + 1.0/Mu[i] * ui * vi * ds(1) # Create the system matrix, preconditioner, and the right-hand sides. # For preconditioners, there are two approaches. The first one, described # in # # Algebraic Multigrid for Complex Symmetric Systems; # D. Lahaye, H. De Gersem, S. Vandewalle, and K. Hameyer; # <https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=877730> # # doesn't work too well here. # The matrix P, created in _build_system(), provides a better alternative. # For more details, see documentation in _build_system(). # A, P, b_list, M, W = _build_system(V, dx, Mu, Sigma, # dictionaries omega, f_list, # list of dicts convections, # dict bcs ) #from matplotlib import pyplot as pp #rows, cols, values = M.data() #from scipy.sparse import csr_matrix #M_matrix = csr_matrix((values, cols, rows)) ##from matplotlib import pyplot as pp ###pp.spy(M_matrix, precision=1e-3, marker='.', markersize=5) ##pp.spy(M_matrix) ##pp.show() ## colormap #cmap = pp.cm.gray_r #M_dense = M_matrix.todense() #from matplotlib.colors import LogNorm #im = pp.imshow(abs(M_dense), cmap=cmap, interpolation='nearest', norm=LogNorm()) ##im = pp.imshow(abs(M_dense), cmap=cmap, interpolation='nearest') ##im = pp.imshow(abs(A_r), cmap=cmap, interpolation='nearest') ##im = pp.imshow(abs(A_i), cmap=cmap, interpolation='nearest') #pp.colorbar() #pp.show() #exit() #print A #rows, cols, values = A.data() #from scipy.sparse import csr_matrix #A_matrix = csr_matrix((values, cols, rows)) ###pp.spy(A_matrix, precision=1e-3, marker='.', markersize=5) ##pp.spy(A_matrix) ##pp.show() ## colormap #cmap = pp.cm.gray_r #A_dense = A_matrix.todense() ##A_r = A_dense[0::2][0::2] ##A_i = A_dense[1::2][0::2] #cmap.set_bad('r') ##im = pp.imshow(abs(A_dense), cmap=cmap, interpolation='nearest', norm=LogNorm()) #im = pp.imshow(abs(A_dense), cmap=cmap, interpolation='nearest') ##im = pp.imshow(abs(A_r), cmap=cmap, interpolation='nearest') ##im = pp.imshow(abs(A_i), cmap=cmap, interpolation='nearest') #pp.colorbar() #pp.show() # prepare solver solver = KrylovSolver('gmres', 'amg') solver.set_operators(A, P) # The PDE for A has huge coefficients (order 10^8) all over. Hence, if # relative residual is set to 10^-6, the actual residual will still be of # the order 10^2. While this isn't too bad (after all the equations are # upscaled by a large factor), one can choose a very small relative # tolerance here to get a visually pleasing residual norm. solver.parameters['relative_tolerance'] = 1.0e-12 solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['maximum_iterations'] = 100 solver.parameters['report'] = verbose solver.parameters['monitor_convergence'] = verbose phi_list = [] for k, b in enumerate(b_list): with Message('Computing coil ring %d/%d...' % (k + 1, len(b_list))): # Define goal functional for adaptivity. # Adaptivity not working for subdomains, cf. # https://bugs.launchpad.net/dolfin/+bug/872105. #(phi_r, phi_i) = split(phi) #M = (phi_r*phi_r + phi_i*phi_i) * dx(2) phi_list.append(Function(W)) phi_list[-1].rename('phi%d' % k, 'phi%d' % k) solver.solve(phi_list[-1].vector(), b) ## Adaptive mesh refinement. #_adaptive_mesh_refinement(dx, # phi_list[-1], # Mu, Sigma, omega, # convections, # f_list[k] # ) #exit() if compute_residuals: # Sanity check: Compute residuals. # This is quite the good test that we haven't messed up # real/imaginary in the above formulation. r_r, r_i = _build_residuals(V, dx, phi_list[-1], omega, Mu, Sigma, convections, voltages ) def xzero(x, on_boundary): return on_boundary and abs(x[0]) < DOLFIN_EPS subdomain_indices = Mu.keys() # Solve an FEM problem to get the corresponding residual function # out. # This is exactly what we need here! :) u = TrialFunction(V) v = TestFunction(V) a = zero() * dx(0) for i in subdomain_indices: a += u * v * dx(i) # TODO don't hard code the boundary conditions like this R_r = Function(V) solve(a == r_r, R_r, bcs=DirichletBC(V, 0.0, xzero) ) # TODO don't hard code the boundary conditions like this R_i = Function(V) solve(a == r_i, R_i, bcs=DirichletBC(V, 0.0, xzero) ) nrm_r = norm(R_r) info('||r_r|| = %e' % nrm_r) nrm_i = norm(R_i) info('||r_i|| = %e' % nrm_i) res_norm = sqrt(nrm_r * nrm_r + nrm_i * nrm_i) info('||r|| = %e' % res_norm) plot(R_r, title='R_r') plot(R_i, title='R_i') interactive() #exit() return phi_list
def ab2tr_step0(u0, P, f, # right-hand side rho, mu, dudt_bcs=[], p_bcs=[], eps=1.0e-4, # relative error tolerance verbose=True ): # Make sure that the initial velocity is divergence-free. alpha = norm(u0, 'Hdiv0') if abs(alpha) > DOLFIN_EPS: warn('Initial velocity not divergence-free (||u||_div = %e).' % alpha ) # Get the initial u0' and p0 by solving the linear equation system # # [M C] [u0'] [f0 - (K+N(u0)u0)] # [C^T 0] [p0 ] = [ g0' ], # # i.e., # # rho u0' + nabla(p0) = f0 + mu\Delta(u0) - rho u0.nabla(u0), # div(u0') = 0. # W = u0.function_space() WP = W*P # Translate the boundary conditions into product space. See # <http://fenicsproject.org/qa/703/boundary-conditions-in-product-space>. dudt_bcs_new = [] for dudt_bc in dudt_bcs: dudt_bcs_new.append(DirichletBC(WP.sub(0), dudt_bc.value(), dudt_bc.user_sub_domain())) p_bcs_new = [] for p_bc in p_bcs: p_bcs_new.append(DirichletBC(WP.sub(1), p_bc.value(), p_bc.user_sub_domain())) new_bcs = dudt_bcs_new + p_bcs_new (u, p) = TrialFunctions(WP) (v, q) = TestFunctions(WP) #a = rho * dot(u, v) * dx + dot(grad(p), v) * dx \ a = rho * inner(u, v) * dx - p * div(v) * dx \ - div(u) * q * dx L = _rhs_weak(u0, v, f, rho, mu) A, b = assemble_system(a, L, new_bcs) # Similar preconditioner as for the Stokes problem. # TODO implement something better! prec = rho * inner(u, v) * dx \ - p*q*dx M, _ = assemble_system(prec, L, new_bcs) solver = KrylovSolver('gmres', 'amg') solver.parameters['monitor_convergence'] = verbose solver.parameters['report'] = verbose solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['relative_tolerance'] = 1.0e-6 solver.parameters['maximum_iterations'] = 10000 # Associate operator (A) and preconditioner matrix (M) solver.set_operators(A, M) #solver.set_operator(A) # Solve up = Function(WP) solver.solve(up.vector(), b) # Get sub-functions dudt0, p0 = up.split() # Choosing the first step size for the trapezoidal rule can be tricky. # Chapters 2.7.4a, 2.7.4e of the book # # Incompressible flow and the finite element method, # volume 1: advection-diffusion; # P.M. Gresho, R.L. Sani, # # give some hints. # # eps ... relative error tolerance # tau ... estimate of the initial 'time constant' tau = None if tau: dt0 = tau * eps**(1.0/3.0) else: # Choose something 'reasonably small'. dt0 = 1.0e-3 # Alternative: # Use a dissipative scheme like backward Euler or BDF2 for the first # couple of steps. This makes sure that noisy initial data is damped # out. return dudt0, p0, dt0
def _pressure_poisson(self, p1, p0, mu, ui, divu, p_bcs=None, p_n=None, rotational_form=False, tol=1.0e-10, verbose=True ): '''Solve the pressure Poisson equation - \Delta phi = -div(u), boundary conditions, for \nabla p = u. ''' P = p1.function_space() p = TrialFunction(P) q = TestFunction(P) a2 = dot(grad(p), grad(q)) * dx L2 = -divu * q * dx if p0: L2 += dot(grad(p0), grad(q)) * dx if p_n: n = FacetNormal(P.mesh()) L2 += dot(n, p_n) * q * ds if rotational_form: L2 -= mu * dot(grad(div(ui)), grad(q)) * dx if p_bcs: solve(a2 == L2, p1, bcs=p_bcs, solver_parameters={ 'linear_solver': 'iterative', 'symmetric': True, 'preconditioner': 'hypre_amg', 'krylov_solver': {'relative_tolerance': tol, 'absolute_tolerance': 0.0, 'maximum_iterations': 100, 'monitor_convergence': verbose} }) else: # If we're dealing with a pure Neumann problem here (which is the # default case), this doesn't hurt CG if the system is consistent, # cf. # # Iterative Krylov methods for large linear systems, # Henk A. van der Vorst. # # And indeed, it is consistent: Note that # # <1, rhs> = \sum_i 1 * \int div(u) v_i # = 1 * \int div(u) \sum_i v_i # = \int div(u). # # With the divergence theorem, we have # # \int div(u) = \int_\Gamma n.u. # # The latter term is 0 iff inflow and outflow are exactly the same # at any given point in time. This corresponds with the # incompressibility of the liquid. # # In turn, this hints towards penetrable boundaries to require # Dirichlet conditions on the pressure. # A = assemble(a2) b = assemble(L2) # # In principle, the ILU preconditioner isn't advised here since it # might destroy the semidefiniteness needed for CG. # # The system is consistent, but the matrix has an eigenvalue 0. # This does not harm the convergence of CG, but when # preconditioning one has to take care that the preconditioner # preserves the kernel. ILU might destroy this (and the # semidefiniteness). With AMG, the coarse grid solves cannot be LU # then, so try Jacobi here. # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html> # prec = PETScPreconditioner('hypre_amg') PETScOptions.set('pc_hypre_boomeramg_relax_type_coarse', 'jacobi') solver = PETScKrylovSolver('cg', prec) solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['relative_tolerance'] = tol solver.parameters['maximum_iterations'] = 100 solver.parameters['monitor_convergence'] = verbose # Create solver and solve system A_petsc = as_backend_type(A) b_petsc = as_backend_type(b) p1_petsc = as_backend_type(p1.vector()) solver.set_operator(A_petsc) try: solver.solve(p1_petsc, b_petsc) except RuntimeError as error: info('') # Check if the system is indeed consistent. # # If the right hand side is flawed (e.g., by round-off errors), # then it may have a component b1 in the direction of the null # space, orthogonal the image of the operator: # # b = b0 + b1. # # When starting with initial guess x0=0, the minimal achievable # relative tolerance is then # # min_rel_tol = ||b1|| / ||b||. # # If ||b|| is very small, which is the case when ui is almost # divergence-free, then min_rel_to may be larger than the # prescribed relative tolerance tol. # # Use this as a consistency check, i.e., bail out if # # tol < min_rel_tol = ||b1|| / ||b||. # # For computing ||b1||, we use the fact that the null space is # one-dimensional, i.e., b1 = alpha e, and # # e.b = e.(b0 + b1) = e.b1 = alpha ||e||^2, # # so alpha = e.b/||e||^2 and # # ||b1|| = |alpha| ||e|| = e.b / ||e|| # e = Function(P) e.interpolate(Constant(1.0)) evec = e.vector() evec /= norm(evec) alpha = b.inner(evec) normB = norm(b) info('Linear system convergence failure.') info(error.message) message = ('Linear system not consistent! ' '<b,e> = %g, ||b|| = %g, <b,e>/||b|| = %e, tol = %e.') \ % (alpha, normB, alpha/normB, tol) info(message) if tol < abs(alpha) / normB: info('\int div(u) = %e' % assemble(divu * dx)) #n = FacetNormal(Q.mesh()) #info('\int_Gamma n.u = %e' % assemble(dot(n, u)*ds)) #info('\int_Gamma u[0] = %e' % assemble(u[0]*ds)) #info('\int_Gamma u[1] = %e' % assemble(u[1]*ds)) ## Now plot the faulty u on a finer mesh (to resolve the ## quadratic trial functions). #fine_mesh = Q.mesh() #for k in range(1): # fine_mesh = refine(fine_mesh) #V1 = FunctionSpace(fine_mesh, 'CG', 1) #W1 = V1*V1 #uplot = project(u, W1) ##uplot = Function(W1) ##uplot.interpolate(u) #plot(uplot, title='u_tentative') #plot(uplot[0], title='u_tentative[0]') #plot(uplot[1], title='u_tentative[1]') plot(divu, title='div(u_tentative)') interactive() exit() raise RuntimeError(message) else: exit() raise RuntimeError('Linear system failed to converge.') except: exit() return
def compute_pressure( P, p0, mu, ui, u, my_dx, p_bcs=None, rotational_form=False, tol=1.0e-10, verbose=True, ): """Solve the pressure Poisson equation .. math:: \\begin{align} -\\frac{1}{r} \\div(r \\nabla (p_1-p_0)) = -\\frac{1}{r} \\div(r u),\\\\ \\text{(with boundary conditions)}, \\end{align} for :math:`\\nabla p = u`. The pressure correction is based on the update formula .. math:: \\frac{\\rho}{dt} (u_{n+1}-u^*) + \\begin{pmatrix} \\text{d}\\phi/\\text{d}r\\\\ \\text{d}\\phi/\\text{d}z\\\\ \\frac{1}{r} \\text{d}\\phi/\\text{d}\\theta \\end{pmatrix} = 0 with :math:`\\phi = p_{n+1} - p^*` and .. math:: \\frac{1}{r} \\frac{\\text{d}}{\\text{d}r} (r u_r^{(n+1)}) + \\frac{\\text{d}}{\\text{d}z} (u_z^{(n+1)}) + \\frac{1}{r} \\frac{\\text{d}}{\\text{d}\\theta} (u_{\\theta}^{(n+1)}) = 0 With the assumption that u does not change in the direction :math:`\\theta`, one derives .. math:: - \\frac{1}{r} \\div(r \\nabla \\phi) = \\frac{1}{r} \\frac{\\rho}{dt} \\div(r (u_{n+1} - u^*))\\\\ - \\frac{1}{r} \\langle n, r \\nabla \\phi\\rangle = \\frac{1}{r} \\frac{\\rho}{dt} \\langle n, r (u_{n+1} - u^*)\\rangle In its weak form, this is .. math:: \\int r \\langle\\nabla\\phi, \\nabla q\\rangle \\,2 \\pi = - \\frac{\\rho}{dt} \\int \\div(r u^*) q \\, 2 \\pi - \\frac{\\rho}{dt} \\int_{\\Gamma} \\langle n, r (u_{n+1}-u^*)\\rangle q \\, 2\\pi. (The terms :math:`1/r` cancel with the volume elements :math:`2\\pi r`.) If the Dirichlet boundary conditions are applied to both :math:`u^*` and :math:`u_n` (the latter in the velocity correction step), the boundary integral vanishes. If no Dirichlet conditions are given (which is the default case), the system has no unique solution; one eigenvalue is 0. This however, does not hurt CG convergence if the system is consistent, cf. :cite:`vdV03`. And indeed it is consistent if and only if .. math:: \\int_\\Gamma r \\langle n, u\\rangle = 0. This condition makes clear that for incompressible Navier-Stokes, one either needs to make sure that inflow and outflow always add up to 0, or one has to specify pressure boundary conditions. Note that, when using a multigrid preconditioner as is done here, the coarse solver must be chosen such that it preserves the nullspace of the problem. """ W = ui.function_space() r = SpatialCoordinate(W.mesh())[0] p = TrialFunction(P) q = TestFunction(P) a2 = dot(r * grad(p), grad(q)) * 2 * pi * my_dx # The boundary conditions # n.(p1-p0) = 0 # are implicitly included. # # L2 = -div(r*u) * q * 2*pi*my_dx div_u = 1 / r * (r * u[0]).dx(0) + u[1].dx(1) L2 = -div_u * q * 2 * pi * r * my_dx if p0: L2 += r * dot(grad(p0), grad(q)) * 2 * pi * my_dx # In the Cartesian variant of the rotational form, one makes use of the # fact that # # curl(curl(u)) = grad(div(u)) - div(grad(u)). # # The same equation holds true in cylindrical form. Hence, to get the # rotational form of the splitting scheme, we need to # # rotational form if rotational_form: # If there is no dependence of the angular coordinate, what is # div(grad(div(u))) in Cartesian coordinates becomes # # 1/r div(r * grad(1/r div(r*u))) # # in cylindrical coordinates (div and grad are in cylindrical # coordinates). Unfortunately, we cannot write it down that # compactly since u_phi is in the game. # When using P2 elements, this value will be 0 anyways. div_ui = 1 / r * (r * ui[0]).dx(0) + ui[1].dx(1) grad_div_ui = as_vector((div_ui.dx(0), div_ui.dx(1))) L2 -= r * mu * dot(grad_div_ui, grad(q)) * 2 * pi * my_dx # div_grad_div_ui = 1/r * (r * grad_div_ui[0]).dx(0) \ # + (grad_div_ui[1]).dx(1) # L2 += mu * div_grad_div_ui * q * 2*pi*r*dx # n = FacetNormal(Q.mesh()) # L2 -= mu * (n[0] * grad_div_ui[0] + n[1] * grad_div_ui[1]) \ # * q * 2*pi*r*ds p1 = Function(P) if p_bcs: solve( a2 == L2, p1, bcs=p_bcs, solver_parameters={ "linear_solver": "iterative", "symmetric": True, "preconditioner": "hypre_amg", "krylov_solver": { "relative_tolerance": tol, "absolute_tolerance": 0.0, "maximum_iterations": 100, "monitor_convergence": verbose, }, }, ) else: # If we're dealing with a pure Neumann problem here (which is the # default case), this doesn't hurt CG if the system is consistent, # cf. :cite:`vdV03`. And indeed it is consistent if and only if # # \int_\Gamma r n.u = 0. # # This makes clear that for incompressible Navier-Stokes, one # either needs to make sure that inflow and outflow always add up # to 0, or one has to specify pressure boundary conditions. # # If the right-hand side is very small, round-off errors may impair # the consistency of the system. Make sure the system we are # solving remains consistent. A = assemble(a2) b = assemble(L2) # Assert that the system is indeed consistent. e = Function(P) e.interpolate(Constant(1.0)) evec = e.vector() evec /= norm(evec) alpha = b.inner(evec) normB = norm(b) # Assume that in every component of the vector, a round-off error # of the magnitude DOLFIN_EPS is present. This leads to the # criterion # |<b,e>| / (||b||*||e||) < DOLFIN_EPS # as a check whether to consider the system consistent up to # round-off error. # # TODO think about condition here # if abs(alpha) > normB * DOLFIN_EPS: if abs(alpha) > normB * 1.0e-12: # divu = 1 / r * (r * u[0]).dx(0) + u[1].dx(1) adivu = assemble(((r * u[0]).dx(0) + u[1].dx(1)) * 2 * pi * my_dx) info("\\int 1/r * div(r*u) * 2*pi*r = {:e}".format(adivu)) n = FacetNormal(P.mesh()) boundary_integral = assemble((n[0] * u[0] + n[1] * u[1]) * 2 * pi * r * ds) info("\\int_Gamma n.u * 2*pi*r = {:e}".format(boundary_integral)) message = ( "System not consistent! " "<b,e> = {:g}, ||b|| = {:g}, <b,e>/||b|| = {:e}.".format( alpha, normB, alpha / normB ) ) info(message) # # Plot the stuff, and project it to a finer mesh with linear # # elements for the purpose. # plot(divu, title='div(u_tentative)') # # Vp = FunctionSpace(Q.mesh(), 'CG', 2) # # Wp = MixedFunctionSpace([Vp, Vp]) # # up = project(u, Wp) # fine_mesh = Q.mesh() # for k in range(1): # fine_mesh = refine(fine_mesh) # V = FunctionSpace(fine_mesh, 'CG', 1) # W = V * V # # uplot = Function(W) # # uplot.interpolate(u) # uplot = project(u, W) # plot(uplot[0], title='u_tentative[0]') # plot(uplot[1], title='u_tentative[1]') # # plot(u, title='u_tentative') # interactive() # exit() raise RuntimeError(message) # Project out the roundoff error. b -= alpha * evec # # In principle, the ILU preconditioner isn't advised here since it # might destroy the semidefiniteness needed for CG. # # The system is consistent, but the matrix has an eigenvalue 0. # This does not harm the convergence of CG, but when # preconditioning one has to make sure that the preconditioner # preserves the kernel. ILU might destroy this (and the # semidefiniteness). With AMG, the coarse grid solves cannot be LU # then, so try Jacobi here. # <http://lists.mcs.anl.gov/pipermail/petsc-users/2012-February/012139.html> # prec = PETScPreconditioner("hypre_amg") from dolfin import PETScOptions PETScOptions.set("pc_hypre_boomeramg_relax_type_coarse", "jacobi") solver = PETScKrylovSolver("cg", prec) solver.parameters["absolute_tolerance"] = 0.0 solver.parameters["relative_tolerance"] = tol solver.parameters["maximum_iterations"] = 100 solver.parameters["monitor_convergence"] = verbose # Create solver and solve system A_petsc = as_backend_type(A) b_petsc = as_backend_type(b) p1_petsc = as_backend_type(p1.vector()) solver.set_operator(A_petsc) solver.solve(p1_petsc, b_petsc) return p1
def test(show=False): problem = problems.Crucible() # The voltage is defined as # # v(t) = Im(exp(i omega t) v) # = Im(exp(i (omega t + arg(v)))) |v| # = sin(omega t + arg(v)) |v|. # # Hence, for a lagging voltage, arg(v) needs to be negative. voltages = [ 38.0 * numpy.exp(-1j * 2 * pi * 2 * 70.0 / 360.0), 38.0 * numpy.exp(-1j * 2 * pi * 1 * 70.0 / 360.0), 38.0 * numpy.exp(-1j * 2 * pi * 0 * 70.0 / 360.0), 25.0 * numpy.exp(-1j * 2 * pi * 0 * 70.0 / 360.0), 25.0 * numpy.exp(-1j * 2 * pi * 1 * 70.0 / 360.0), ] lorentz, joule, Phi = get_lorentz_joule(problem, voltages, show=show) # Some assertions ref = 1.4627674791126285e-05 assert abs(norm(Phi[0], "L2") - ref) < 1.0e-3 * ref ref = 3.161363929287592e-05 assert abs(norm(Phi[1], "L2") - ref) < 1.0e-3 * ref # ref = 12.115309575057681 assert abs(norm(lorentz, "L2") - ref) < 1.0e-3 * ref # ref = 1406.336109054347 V = FunctionSpace(problem.submesh_workpiece, "CG", 1) jp = project(joule, V) jp.rename("s", "Joule heat source") assert abs(norm(jp, "L2") - ref) < 1.0e-3 * ref # check_currents = False # if check_currents: # r = SpatialCoordinate(problem.mesh)[0] # begin('Currents computed after the fact:') # k = 0 # with XDMFFile('currents.xdmf') as xdmf_file: # for coil in coils: # for ii in coil['rings']: # J_r = sigma[ii] * ( # voltages[k].real/(2*pi*r) + problem.omega * Phi[1] # ) # J_i = sigma[ii] * ( # voltages[k].imag/(2*pi*r) - problem.omega * Phi[0] # ) # alpha = assemble(J_r * dx(ii)) # beta = assemble(J_i * dx(ii)) # info('J = {:e} + i {:e}'.format(alpha, beta)) # info( # '|J|/sqrt(2) = {:e}'.format( # numpy.sqrt(0.5 * (alpha**2 + beta**2)) # )) # submesh = SubMesh(problem.mesh, problem.subdomains, ii) # V1 = FunctionSpace(submesh, 'CG', 1) # # Those projections may take *very* long. # # TODO find out why # j_v1 = [ # project(J_r, V1), # project(J_i, V1) # ] # # show=Trueplot(j_v1[0], title='j_r') # # plot(j_v1[1], title='j_i') # current = project(as_vector(j_v1), V1*V1) # current.rename('j{}'.format(ii), 'current {}'.format(ii)) # xdmf_file.write(current) # k += 1 # end() filename = "./maxwell.xdmf" with XDMFFile(filename) as xdmf_file: xdmf_file.parameters["flush_output"] = True xdmf_file.parameters["rewrite_function_mesh"] = False # Store phi info("Writing out Phi to {}...".format(filename)) V = FunctionSpace(problem.mesh, "CG", 1) phi = Function(V, name="phi") Phi0 = project(Phi[0], V) Phi1 = project(Phi[1], V) omega = problem.omega for t in numpy.linspace(0.0, 2 * pi / omega, num=100, endpoint=False): # Im(Phi * exp(i*omega*t)) phi.vector().zero() phi.vector().axpy(sin(problem.omega * t), Phi0.vector()) phi.vector().axpy(cos(problem.omega * t), Phi1.vector()) xdmf_file.write(phi, t) # Show the resulting magnetic field # # B_r = -dphi/dz, # B_z = 1/r d(rphi)/dr. # r = SpatialCoordinate(problem.mesh)[0] g = 1.0 / r * grad(r * Phi[0]) V_element = FiniteElement("CG", V.mesh().ufl_cell(), 1) VV = FunctionSpace(V.mesh(), V_element * V_element) B_r = project(as_vector((-g[1], g[0])), VV) g = 1 / r * grad(r * Phi[1]) B_i = project(as_vector((-g[1], g[0])), VV) info("Writing out B to {}...".format(filename)) B = Function(VV) B.rename("B", "magnetic field") if abs(problem.omega) < DOLFIN_EPS: B.assign(B_r) xdmf_file.write(B) # plot(B_r, title='Re(B)') # plot(B_i, title='Im(B)') else: # Write those out to a file. lspace = numpy.linspace( 0.0, 2 * pi / problem.omega, num=100, endpoint=False ) for t in lspace: # Im(B * exp(i*omega*t)) B.vector().zero() B.vector().axpy(sin(problem.omega * t), B_r.vector()) B.vector().axpy(cos(problem.omega * t), B_i.vector()) xdmf_file.write(B, t) filename = "./lorentz-joule.xdmf" info("Writing out Lorentz force and Joule heat source to {}...".format(filename)) with XDMFFile(filename) as xdmf_file: xdmf_file.write(lorentz, 0.0) # xdmf_file.write(jp, 0.0) return
def test_estimator_refinement(): # define source term f = Constant("1.0") # f = Expression("10.*exp(-(pow(x[0] - 0.6, 2) + pow(x[1] - 0.4, 2)) / 0.02)", degree=3) # set default vector for new indices mesh0 = refine(Mesh(lshape_xml)) fs0 = FunctionSpace(mesh0, "CG", 1) B = FEniCSBasis(fs0) u0 = Function(fs0) diffcoeff = Constant("1.0") pde = FEMPoisson() fem_A = pde.assemble_lhs(diffcoeff, B) fem_b = pde.assemble_rhs(f, B) solve(fem_A, u0.vector(), fem_b) vec0 = FEniCSVector(u0) # setup solution multi vector mis = [Multiindex([0]), Multiindex([1]), Multiindex([0, 1]), Multiindex([0, 2])] N = len(mis) # meshes = [UnitSquare(i + 3, 3 + N - i) for i in range(N)] meshes = [refine(Mesh(lshape_xml)) for _ in range(N)] fss = [FunctionSpace(mesh, "CG", 1) for mesh in meshes] # solve Poisson problem w = MultiVectorWithProjection() for i, mi in enumerate(mis): B = FEniCSBasis(fss[i]) u = Function(fss[i]) pde = FEMPoisson() fem_A = pde.assemble_lhs(diffcoeff, B) fem_b = pde.assemble_rhs(f, B) solve(fem_A, u.vector(), fem_b) w[mi] = FEniCSVector(u) # plot(w[mi]._fefunc) # define coefficient field a0 = Expression("1.0", element=FiniteElement('Lagrange', ufl.triangle, 1)) # a = [Expression('2.+sin(2.*pi*I*x[0]+x[1]) + 10.*exp(-pow(I*(x[0] - 0.6)*(x[1] - 0.3), 2) / 0.02)', I=i, degree=3, a = (Expression('A*cos(pi*I*x[0])*cos(pi*I*x[1])', A=1 / i ** 2, I=i, degree=2, element=FiniteElement('Lagrange', ufl.triangle, 1)) for i in count()) rvs = (NormalRV(mu=0.5) for _ in count()) coeff_field = ParametricCoefficientField(a, rvs, a0=a0) # refinement loop # =============== refinements = 3 for refinement in range(refinements): print "*****************************" print "REFINEMENT LOOP iteration ", refinement + 1 print "*****************************" # evaluate residual and projection error estimates # ================================================ maxh = 1 / 10 resind, reserr = ResidualEstimator.evaluateResidualEstimator(w, coeff_field, f) projind, projerr = ResidualEstimator.evaluateProjectionError(w, coeff_field, maxh) # testing --> projglobal, _ = ResidualEstimator.evaluateProjectionError(w, coeff_field, maxh, local=False) for mu, val in projglobal.iteritems(): print "GLOBAL Projection Error for", mu, "=", val # <-- testing # ============== # MARK algorithm # ============== # setup marking sets mesh_markers = defaultdict(set) # residual marking # ================ theta_eta = 0.8 global_res = sum([res[1] for res in reserr.items()]) allresind = list() for mu, resmu in resind.iteritems(): allresind = allresind + [(resmu.coeffs[i], i, mu) for i in range(len(resmu.coeffs))] allresind = sorted(allresind, key=itemgetter(1)) # TODO: check that indexing and cell ids are consistent (it would be safer to always work with cell indices) marked_res = 0 for res in allresind: if marked_res >= theta_eta * global_res: break mesh_markers[res[2]].add(res[1]) marked_res += res[0] print "RES MARKED elements:\n", [(mu, len(cell_ids)) for mu, cell_ids in mesh_markers.iteritems()] # projection marking # ================== theta_zeta = 0.8 min_zeta = 1e-10 max_zeta = max([max(projind[mu].coeffs) for mu in projind.active_indices()]) print "max_zeta =", max_zeta if max_zeta >= min_zeta: for mu, vec in projind.iteritems(): indmu = [i for i, p in enumerate(vec.coeffs) if p >= theta_zeta * max_zeta] mesh_markers[mu] = mesh_markers[mu].union(set(indmu)) print "PROJ MARKING", len(indmu), "elements in", mu print "FINAL MARKED elements:\n", [(mu, len(cell_ids)) for mu, cell_ids in mesh_markers.iteritems()] else: print "NO PROJECTION MARKING due to very small projection error!" # new multiindex activation # ========================= # determine possible new indices theta_delta = 0.9 maxm = 10 a0_f = coeff_field.mean_func Ldelta = {} Delta = w.active_indices() deltaN = int(ceil(0.1 * len(Delta))) # max number new multiindices for mu in Delta: norm_w = norm(w[mu].coeffs, 'L2') for m in count(): mu1 = mu.inc(m) if mu1 not in Delta: if m > maxm or m >= coeff_field.length: # or len(Ldelta) >= deltaN break am_f, am_rv = coeff_field[m] beta = am_rv.orth_polys.get_beta(1) # determine ||a_m/\overline{a}||_{L\infty(D)} (approximately) f = Function(w[mu]._fefunc.function_space()) f.interpolate(a0_f) min_a0 = min(f.vector().array()) f.interpolate(am_f) max_am = max(f.vector().array()) ainfty = max_am / min_a0 assert isinstance(ainfty, float) # print "A***", beta[1], ainfty, norm_w # print "B***", beta[1] * ainfty * norm_w # print "C***", theta_delta, max_zeta # print "D***", theta_delta * max_zeta # print "E***", bool(beta[1] * ainfty * norm_w >= theta_delta * max_zeta) if beta[1] * ainfty * norm_w >= theta_delta * max_zeta: val1 = beta[1] * ainfty * norm_w if mu1 not in Ldelta.keys() or (mu1 in Ldelta.keys() and Ldelta[mu1] < val1): Ldelta[mu1] = val1 print "POSSIBLE NEW MULTIINDICES ", sorted(Ldelta.iteritems(), key=itemgetter(1), reverse=True) Ldelta = sorted(Ldelta.iteritems(), key=itemgetter(1), reverse=True)[:min(len(Ldelta), deltaN)] # add new multiindices to solution vector for mu, _ in Ldelta: w[mu] = vec0 print "SELECTED NEW MULTIINDICES ", Ldelta # create new refined (and enlarged) multi vector # ============================================== for mu, cell_ids in mesh_markers.iteritems(): vec = w[mu].refine(cell_ids, with_prolongation=False) fs = vec._fefunc.function_space() B = FEniCSBasis(fs) u = Function(fs) pde = FEMPoisson() fem_A = pde.assemble_lhs(diffcoeff, B) fem_b = pde.assemble_rhs(f, B) solve(fem_A, vec.coeffs, fem_b) w[mu] = vec