def estimate_mark(cls, w, coeff_field, pde, f, theta_eta, theta_zeta, theta_delta, min_zeta, maxh=1 / 10, maxm=10, quadrature_degree= -1, projection_degree_increase=0, refine_projection_mesh=0): """Convenience method which evaluates the residual and the projection indicators and then calls the marking algorithm.""" # # testing --> # if logger.isEnabledFor(logging.DEBUG): # projglobal, _ = ResidualEstimator.evaluateProjectionError(w, coeff_field, maxh, local=False) # for mu, val in projglobal.iteritems(): # logger.debug("GLOBAL Projection Error for %s = %f", mu, val) # # <-- testing # evaluate residual estimator resind, _ = ResidualEstimator.evaluateResidualEstimator(w, coeff_field, pde, f, quadrature_degree) # evaluate projection errors projind, _ = ResidualEstimator.evaluateProjectionError(w, coeff_field, maxh, projection_degree_increase, refine_projection_mesh) # evaluate inanctive mi projection error mierr = ResidualEstimator.evaluateInactiveMIProjectionError(w, coeff_field, maxh, maxm) # mark return cls.mark(resind, projind, mierr, w.max_order, theta_eta, theta_zeta, theta_delta, min_zeta, maxh, maxm)
def test_estimator(): # setup solution multi vector mis = [Multiindex([0]), Multiindex([1]), Multiindex([0, 1]), Multiindex([0, 2])] mesh = UnitSquare(4, 4) fs = FunctionSpace(mesh, "CG", 1) F = [interpolate(Expression("*".join(["x[0]"] * i)), fs) for i in range(1, 5)] vecs = [FEniCSVector(f) for f in F] w = MultiVectorWithProjection() for mi, vec in zip(mis, vecs): w[mi] = vec # v = A * w # define coefficient field aN = 4 a = [Expression('2.+sin(20.*pi*I*x[0]*x[1])', I=i, degree=3, element=fs.ufl_element()) for i in range(1, aN)] rvs = [UniformRV(), NormalRV(mu=0.5)] coeff_field = ListCoefficientField(a[0], a[1:], rvs) # define source term f = Constant("1.0") # evaluate residual and projection error estimators resind, reserr = ResidualEstimator.evaluateResidualEstimator(w, coeff_field, f) projind, projerr = ResidualEstimator.evaluateProjectionError(w, coeff_field) print resind[mis[0]].as_array().shape, projind[mis[0]].as_array().shape print "RESIDUAL:", resind[mis[0]].as_array() print "PROJECTION:", projind[mis[0]].as_array() print "residual error estimate for mu" for mu in reserr: print "\t eta", mu, " is ", reserr[mu] print "\t delta", mu, " is ", projerr[mu] assert_equal(w.active_indices(), resind.active_indices()) print "active indices are ", resind.active_indices()
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
def AdaptiveSolver(A, coeff_field, pde, mis, w0, mesh0, degree, gamma=0.9, cQ=1.0, ceta=6.0, # marking parameters theta_eta=0.4, # residual marking bulk parameter theta_zeta=0.1, # projection marking threshold factor min_zeta=1e-8, # minimal projection error to be considered maxh=0.1, # maximal mesh width for projection maximum norm evaluation newmi_add_maxm=20, # maximal search length for new new multiindices (to be added to max order of solution w) theta_delta=10.0, # number new multiindex activation bound max_Lambda_frac=1 / 10, # max fraction of |Lambda| for new multiindices marking_strategy="SEPARATE with CELLPROJECTION", # separate (as initially in EGSZ) or relative marking wrt overall error, projection refinement based on cell or mesh errors # residual error quadrature_degree= -1, # projection error projection_degree_increase=1, refine_projection_mesh=1, # pcg solver pcg_eps=1e-6, pcg_maxiter=100, # adaptive algorithm threshold error_eps=1e-2, # refinements max_refinements=5, max_dof=1e10, do_refinement={"RES":True, "PROJ":True, "MI":False}, do_uniform_refinement=False, w_history=None, sim_stats=None): # define store function for timings from functools import partial def _store_stats(val, key, stats): stats[key] = val # define tuple type EstimatorData = namedtuple('EstimatorData', ['xi', 'gamma', 'cQ', 'ceta']) # get rhs f = pde.f # setup w and statistics w = w0 if sim_stats is None: assert w_history is None or len(w_history) == 0 sim_stats = [] try: start_iteration = max(len(sim_stats) - 1, 0) except: start_iteration = 0 logger.info("START/CONTINUE EXPERIMENT at iteration %i", start_iteration) # data collection import resource refinement = None for refinement in range(start_iteration, max_refinements + 1): logger.info("************* REFINEMENT LOOP iteration %i (of %i or max_dof %i) *************", refinement, max_refinements, max_dof) # memory usage info logger.info("\n======================================\nMEMORY USED: " + str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) + "\n======================================\n") # pcg solve # --------- stats = {} with timing(msg="pcg_solve", logfunc=logger.info, store_func=partial(_store_stats, key="TIME-PCG", stats=stats)): w, zeta = pcg_solve(A, w, coeff_field, pde, stats, pcg_eps, pcg_maxiter) logger.info("DIM of w = %s", w.dim) if w_history is not None and (refinement == 0 or start_iteration < refinement): w_history.append(w) # error evaluation # ---------------- # residual and projection errors logger.debug("evaluating ResidualEstimator.evaluateError") with timing(msg="ResidualEstimator.evaluateError", logfunc=logger.info, store_func=partial(_store_stats, key="TIME-ESTIMATOR", stats=stats)): xi, resind, projind, mierror, estparts, errors, timing_stats = ResidualEstimator.evaluateError(w, coeff_field, pde, f, zeta, gamma, ceta, cQ, newmi_add_maxm, maxh, quadrature_degree, projection_degree_increase, refine_projection_mesh) reserrmu = [(mu, sqrt(sum(resind[mu].coeffs ** 2))) for mu in resind.keys()] projerrmu = [(mu, sqrt(sum(projind[mu].coeffs ** 2))) for mu in projind.keys()] res_part, proj_part, pcg_part = estparts[0], estparts[1], estparts[2] err_res, err_proj, err_pcg = errors[0], errors[1], errors[2] logger.info("Overall Estimator Error xi = %s while residual error is %s, projection error is %s, pcg error is %s", xi, res_part, proj_part, pcg_part) stats.update(timing_stats) stats["EST"] = xi stats["RES-PART"] = res_part stats["PROJ-PART"] = proj_part stats["PCG-PART"] = pcg_part stats["ERR-RES"] = err_res stats["ERR-PROJ"] = err_proj stats["ERR-PCG"] = err_pcg stats["ETA-ERR"] = errors[0] stats["DELTA-ERR"] = errors[1] stats["ZETA-ERR"] = errors[2] stats["RES-mu"] = reserrmu stats["PROJ-mu"] = projerrmu stats["PROJ-MAX-ZETA"] = 0 stats["PROJ-MAX-INACTIVE-ZETA"] = 0 stats["MARKING-RES"] = 0 stats["MARKING-PROJ"] = 0 stats["MARKING-MI"] = 0 stats["TIME-MARKING"] = 0 stats["MI"] = [(mu, vec.basis.dim) for mu, vec in w.iteritems()] if refinement == 0 or start_iteration < refinement: sim_stats.append(stats) # print "SIM_STATS:", sim_stats[refinement] logger.debug("squared error components: eta=%s delta=%s zeta=%", errors[0], errors[1], errors[2]) # exit when either error threshold or max_refinements or max_dof is reached if refinement > max_refinements: logger.info("SKIPPING REFINEMENT after FINAL SOLUTION in ITERATION %i", refinement) break if sim_stats[refinement]["DOFS"] >= max_dof: logger.info("REACHED %i DOFS, EXITING refinement loop", sim_stats[refinement]["DOFS"]) break if xi <= error_eps: logger.info("error reached requested accuracy, xi=%f", xi) break # marking # ------- if refinement < max_refinements: if not do_uniform_refinement: logger.debug("starting Marking.mark") estimator_data = EstimatorData(xi=xi, gamma=gamma, cQ=cQ, ceta=ceta) mesh_markers_R, mesh_markers_P, new_multiindices, proj_zeta, new_multiindices_all = Marking.mark(resind, projind, mierror, w.max_order, theta_eta, theta_zeta, theta_delta, min_zeta, maxh, max_Lambda_frac, estimator_data, marking_strategy) sim_stats[-1]["PROJ-MAX-ZETA"] = proj_zeta[0] sim_stats[-1]["PROJ-MAX-INACTIVE-ZETA"] = proj_zeta[1] sim_stats[-1]["PROJ-INACTIVE-ZETA"] = new_multiindices_all # assert len(new_multiindices_all) == 0 or proj_zeta[1] == max([v for v in new_multiindices_all.values()]) logger.info("PROJECTION error values: max_zeta = %s and max_inactive_zeta = %s with threshold factor theta_zeta = %s (=%s)", proj_zeta[0], proj_zeta[1], theta_zeta, theta_zeta * proj_zeta[0]) logger.info("MARKING will be carried out with %s (res) + %s (proj) cells and %s new multiindices", sum([len(cell_ids) for cell_ids in mesh_markers_R.itervalues()]), sum([len(cell_ids) for cell_ids in mesh_markers_P.itervalues()]), len(new_multiindices)) stats["MARKING-RES"] = sum([len(cell_ids) for cell_ids in mesh_markers_R.itervalues()]) stats["MARKING-PROJ"] = sum([len(cell_ids) for cell_ids in mesh_markers_P.itervalues()]) stats["MARKING-MI"] = len(new_multiindices) if do_refinement["RES"]: mesh_markers = mesh_markers_R.copy() else: mesh_markers = defaultdict(set) logger.info("SKIP residual refinement") if do_refinement["PROJ"]: for mu, cells in mesh_markers_P.iteritems(): if len(cells) > 0: mesh_markers[mu] = mesh_markers[mu].union(cells) else: logger.info("SKIP projection refinement") if not do_refinement["MI"] or refinement == max_refinements: new_multiindices = {} logger.info("SKIP new multiindex refinement") else: logger.info("UNIFORM REFINEMENT active") mesh_markers = {} for mu, vec in w.iteritems(): from dolfin import cells mesh_markers[mu] = list([c.index() for c in cells(vec._fefunc.function_space().mesh())]) new_multiindices = {} # carry out refinement of meshes with timing(msg="Marking.refine", logfunc=logger.info, store_func=partial(_store_stats, key="TIME-MARKING", stats=stats)): Marking.refine(w, mesh_markers, new_multiindices.keys(), partial(setup_vector, pde=pde, mesh=mesh0, degree=degree)) if refinement: logger.info("ENDED refinement loop after %i of %i refinements with %i dofs and %i active multiindices", refinement, max_refinements, sim_stats[refinement]["DOFS"], len(sim_stats[refinement]["MI"])) # except Exception as ex: # import pickle # logger.error("EXCEPTION during AdaptiveSolver: %s", str(ex)) # print "DIM of w:", w.dim # if not w_history is None: # w_history.append(w) # wname = "W-PCG-FAILED.pkl" # try: # with open(wname, 'wb') as fout: # pickle.dump(w, fout) # except Exception as ex: # logger.error("NEXT EXCEPTION %s", str(ex)) # logger.info("exported last multivector w to %s", wname) # finally: return w, sim_stats