Exemple #1
0
    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
Exemple #4
0
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