Exemplo n.º 1
0
    def _assemble_and_solve_adj_eq(self, dFdu_adj_form, dJdu, compute_bdy):
        dJdu_copy = dJdu.copy()
        bcs = self._homogenize_bcs()

        solver = self.block_helper.adjoint_solver
        if solver is None:
            if self.assemble_system:
                rhs_bcs_form = backend.inner(backend.Function(self.function_space),
                                             dFdu_adj_form.arguments()[0]) * backend.dx
                A, _ = backend.assemble_system(dFdu_adj_form, rhs_bcs_form, bcs)
            else:
                A = compat.assemble_adjoint_value(dFdu_adj_form)
                [bc.apply(A) for bc in bcs]

            solver = backend.LUSolver(A, self.method)
            self.block_helper.adjoint_solver = solver

        solver.parameters.update(self.lu_solver_parameters)
        [bc.apply(dJdu) for bc in bcs]

        adj_sol = backend.Function(self.function_space)
        solver.solve(adj_sol.vector(), dJdu)

        adj_sol_bdy = None
        if compute_bdy:
            adj_sol_bdy = compat.function_from_vector(self.function_space, dJdu_copy - compat.assemble_adjoint_value(
                backend.action(dFdu_adj_form, adj_sol)))

        return adj_sol, adj_sol_bdy
Exemplo n.º 2
0
    def _forward_solve(self, lhs, rhs, func, bcs, **kwargs):
        solver = self.block_helper.forward_solver
        if solver is None:
            if self.assemble_system:
                A, _ = backend.assemble_system(lhs, rhs, bcs,
                                               **self.assemble_kwargs)
            else:
                A = compat.assemble_adjoint_value(lhs, **self.assemble_kwargs)
                [bc.apply(A) for bc in bcs]

            solver = backend.LUSolver(A, self.method)
            self.block_helper.forward_solver = solver

        if self.assemble_system:
            system_assembler = backend.SystemAssembler(lhs, rhs, bcs)
            b = backend.Function(self.function_space).vector()
            system_assembler.assemble(b)
        else:
            b = compat.assemble_adjoint_value(rhs)
            [bc.apply(b) for bc in bcs]

        if self.ident_zeros_tol is not None:
            A.ident_zeros(self.ident_zeros_tol)

        solver.parameters.update(self.lu_solver_parameters)
        solver.solve(func.vector(), b)
        return func
Exemplo n.º 3
0
 def __init__(self, problem: ProblemForm, fields: Fields,
              boundary_conditions: List[fenics.DirichletBC]):
     super().__init__(problem, fields, boundary_conditions)
     self.a_form = problem.get_weak_form_lhs(fields=fields)
     self.L_form = problem.get_weak_form_rhs(fields=fields)
     self.boundary_conditions = boundary_conditions
     self.K, _ = fenics.assemble_system(self.a_form, self.L_form,
                                        self.boundary_conditions)
     self.solver = fenics.LUSolver(self.K, "mumps")
     self.solver.parameters["symmetric"] = True
Exemplo n.º 4
0
 def _get_solvers_and_y():
     if not bilinear_form_is_symmetric:
         # Homogenized and original boundary conditions have equivalent effect on matrix
         # corresponding to assembled bilinear form
         A_solver = construct_solver(A, boundary_conditions)
         b_vector = fenics.assemble(b)
         adjoint_A_solver = construct_solver(
             adjoint_A, homogenized_boundary_conditions)
         solve_with_boundary_conditions(A_solver, boundary_conditions,
                                        b_vector, x)
     else:
         A_matrix, b_vector = fenics.assemble_system(
             A, b, boundary_conditions)
         A_solver = fenics.LUSolver(A_matrix)
         A_solver.parameters["symmetric"] = True
         adjoint_A_solver = A_solver  # A is symmetric therefore adjoint(A) == A
         A_solver.solve(x.vector(), b_vector)
     y = (x.vector()).get_local()[observation_dof_indices]
     return A_solver, adjoint_A_solver, y
def test_minexample():
    import scipy.integrate
    import fenics as fe
    import numpy as np
    import magnics

    # Material parameters
    Ms = 8.6e5  # saturation magnetisation (A/m)
    alpha = 0.1  # Gilbert damping
    gamma = 2.211e5  # gyromagnetic ratio
    A = 1e-11 # exchange constant (J/m)
    #A = 0
    D = 0*1.58e-3 # DMI constant (FeGe: D = 1.58e-3 J/m²)
    K = 0*5e3 # anisotropy constant (Co: K = 4.5e5 J/m³)

    # External magnetic field.
    B = 0.1  # (T)
    mu0 = 4 * np.pi * 1e-7  # vacuum permeability

    # Zeeman field
    H = Ms / 2 * fe.Constant((0,0,1))
    # easy axis
    ea = fe.Constant((0,1,1))

    # mesh parameters
    d = 100e-9
    thickness = 100e-9
    nx = ny = 20
    nz = 10

    # create mesh
    p1 = fe.Point(0, 0, 0)
    p2 = fe.Point(d, d, thickness)
    mesh = fe.BoxMesh(p1, p2, nx, ny, nz)


    m, Heff, u, v, V = magnics.vectorspace(mesh)

    def effective_field(m, volume=None):
        w_Zeeman = - mu0 * Ms * fe.dot(m, H)
        w_exchange = A  * fe.inner(fe.grad(m), fe.grad(m))
        w_DMI = D * fe.inner(m, fe.curl(m))
        w_ani = - K * fe.inner(m, ea)**2
        w = w_Zeeman + w_exchange + w_DMI + w_ani
        return -1/(mu0*Ms) * fe.derivative(w*fe.dx, m)

    # Effective field
    Heff_form = effective_field(m)

    # Preassemble projection Matrix
    Amat = fe.assemble(fe.dot(u, v)*fe.dx)

    LU = fe.LUSolver()
    LU.set_operator(Amat)


    def compute_dmdt(m):
        """Convenience function that does all in one go"""

        # Assemble RHS
        b = fe.assemble(Heff_form)

        # Project onto Heff
        LU.solve(Heff.vector(), b)

        LLG = -gamma/(1+alpha*alpha)*fe.cross(m, Heff) - alpha*gamma/(1+alpha*alpha)*fe.cross(m, fe.cross(m, Heff))

        result = fe.assemble(fe.dot(LLG, v)*fe.dP)
        return result.array()

    # function for integration of system of ODEs

    def rhs_micromagnetic(m_vector_array, t, counter=[0]):
        assert isinstance(m_vector_array, np.ndarray)
        m.vector()[:] = m_vector_array[:]

        dmdt = compute_dmdt(m)
        return dmdt

    m_init = fe.Constant((1, 0, 0))
    m = fe.interpolate(m_init, V)
    ts = np.linspace(0, 1e-11, 100)
    # empty call of time integrator, just to get FEniCS to cache all forms etc
    rhs_micromagnetic(m.vector().array(), 0)

    ms = scipy.integrate.odeint(rhs_micromagnetic, y0=m.vector().array(), t=ts, rtol=1e-10, atol=1e-10)


    def macrospin_analytic_solution(alpha, gamma, H, t_array):
        """
        Computes the analytic solution of magnetisation x component
        as a function of time for the macrospin in applied external
        magnetic field H.

        Source: PhD Thesis Matteo Franchin,
        http://eprints.soton.ac.uk/161207/1.hasCoversheetVersion/thesis.pdf,
        Appendix B, page 127

        """
        t0 = 1 / (gamma * alpha * H) * np.log(np.sin(np.pi / 2) / \
                                              (1 + np.cos(np.pi / 2)))
        mx_analytic = []
        for t in t_array:
            phi = gamma * H * t                                     # (B16)
            costheta = np.tanh(gamma * alpha * H * (t - t0))        # (B17)
            sintheta = 1 / np.cosh(gamma * alpha * H * (t - t0))    # (B18)
            mx_analytic.append(sintheta * np.cos(phi))

        return np.array(mx_analytic)

    mx_analytic = macrospin_analytic_solution(alpha, gamma, Ms/2, ts)

    tmp2 = ms[:,0:1]  # might be m_x, m_y, m_z of first vector

    difference = tmp2[:,0] - mx_analytic
    print("max deviation: {}".format(max(abs(difference))))


    # add quick test
    eps = 0.01
    #ref = 0.0655908475021   # for tmax = 1e-10
    ref = 0.0422068879247    # for tmax = 5e-11
    ref = 0.00765261606231   # for tmax = 1e-11
    assert ref - eps < max(abs(difference)) < ref + eps
Exemplo n.º 6
0
def fwi_si(gt_data, i_guess, n_receivers, noise_lv, path):
    """
    This is the main function of the project.
    Entries 
        gt_data: string path to the ground truth image data
        i_guess: integer pointing the algorithm initialization guess
        n_shots: integer, number of strikes for the FWI
        n_receivers: integer, number of receivers for the FWI
        noise_lv: float type variable that we use to compute noise level
        path: string type variable, path to local results directory
    """

    # Implementing parallel processing at shots level """
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    n_shots = comm.Get_size()

    seism_vel = [4.12, 1.95]
    image_phi = mpimg.imread(gt_data)
    chi0 = np.int64(image_phi == 0)
    chi1 = 1.0 - chi0
    synth_model = seism_vel[0] * chi1 + seism_vel[1] * chi0
    #scale in meter
    xMin = 0.0
    xMax = 1.0
    zMin = 0.0
    zMax = 0.650
    #scale in seconds
    tMin = 0.0
    tMax = 1.0

    # Damping layer width and damping limits
    damp_layer = 0.1 * xMax
    dmp_xMin = xMin + damp_layer
    dmp_xMax = xMax - damp_layer
    dmp_zMax = zMax - damp_layer

    #    Number of grid points are determined by the loaded image size
    #    Nz, Nx are (#) of grid point
    Nz, Nx = synth_model.shape
    delta_x = xMax / Nx
    delta_z = zMax / Nz
    CFL = 0.4
    delta_t = (CFL * min(delta_x, delta_z)) / max(seism_vel)
    gc_t = np.arange(tMin, tMax, delta_t)
    Nt = len(gc_t)

    # Level set parameters
    MainItMax = 5000
    gamma = 0.8
    gamma2 = 0.8
    stop_coeff = 1.0e-8
    add_weight = True
    ls_max = 3
    ls = 0
    beta0_init = 1.5  # 1.2 #0.8 #0.5 #0.3
    beta0 = beta0_init
    beta = beta0
    stop_decision_limit = 150
    stop_decision = 0
    alpha1 = 0.01
    alpha2 = 0.97

    # wave Parameters
    PlotFields = True
    add_noise = False if noise_lv == 0 else True
    src_Zpos = 5.0
    source_peak_frequency = 5.0  # (kilo hertz)

    # Grid coordinates
    gc_x = np.arange(xMin, xMax, delta_x)
    gc_z = np.arange(zMin, zMax, delta_z)

    # Compute receivers
    id_dmp_xMin = np.where(gc_x == dmp_xMin)[0][0]
    id_dmp_xMax = np.where(gc_x == dmp_xMax)[0][0]
    id_dmp_zMax = np.where(gc_z == dmp_zMax)[0][0]
    rec_index = np.linspace(id_dmp_xMin,
                            id_dmp_xMax,
                            n_receivers + 1,
                            dtype='int')
    try:
        assert (len(rec_index) < id_dmp_xMax - id_dmp_xMin)
    except AssertionError:
        "receivers in different positions"

    # Build the HUGE parameter dictionary
    parameters = {
        "gamma": gamma,
        "gamma2": gamma2,
        "ls_max": ls_max,
        "stop_coeff": stop_coeff,
        "add_noise": add_noise,
        "add_weight": add_weight,
        "beta0_init": beta0_init,
        "stop_decision_limit": stop_decision_limit,
        "alpha1": alpha1,
        "alpha2": alpha2,
        "CFL": CFL,
        "source_peak_frequency": source_peak_frequency,
        "src_Zpos": src_Zpos,
        "i_guess": i_guess,
        "n_shots": n_shots,
        "n_receivers": n_receivers,
        "add_weight": add_weight,
        "nz": Nz,
        "nx": Nx,
        "nt": Nt,
        "gc_t": gc_t,
        "gc_x": gc_x,
        "gc_z": gc_z,
        "xMin": xMin,
        "xMax": xMax,
        "zMin": zMin,
        "zMax": zMax,
        "tMin": tMin,
        "tMax": tMax,
        "hz": delta_z,
        "hx": delta_x,
        "ht": delta_t,
        "dmp_xMin": dmp_xMin,
        "dmp_xMax": dmp_xMax,
        "dmp_zMax": dmp_zMax,
        "dmp_layer": damp_layer,
        "id_dmp_xMin": id_dmp_xMin,
        "id_dmp_xMax": id_dmp_xMax,
        "id_dmp_zMax": id_dmp_zMax,
        "rec": gc_x[rec_index],
        "rec_index": rec_index,
        'noise_lv': noise_lv,
        "path": path,
        "path_misfit": path + 'misfit/',
        "path_phi": path + 'phi/'
    }

    # Compute initial guess matrix
    if rank == 0:
        outputs_and_paths(parameters)
        gnu_data(image_phi, 'ground_truth.dat', parameters)
        mkDirectory(parameters["path_phi"])

    comm.Barrier()
    phi_mat = initial_guess(parameters)
    ind = inside_shape(phi_mat)
    ind_c = np.ones_like(phi_mat) - ind
    vel_field = seism_vel[0] * ind + seism_vel[1] * ind_c

    # Initialization of Fenics-Dolfin functions
    # ----------------------------------------
    # Define mesh for the entire domain Omega
    # ----------------------------------------
    mesh = fc.RectangleMesh(comm, fc.Point(xMin, zMin), fc.Point(xMax, zMax),
                            Nx - 1, Nz - 1)
    # ----------------------------------------
    # Function spaces
    # ----------------------------------------
    V = fc.FunctionSpace(mesh, "Lagrange", 1)
    VF = fc.VectorFunctionSpace(mesh, "Lagrange", 1)
    theta = fc.TrialFunction(VF)
    csi = fc.TestFunction(VF)

    # ----------------------------------------
    # Define boundaries of the domain
    # ----------------------------------------
    tol = fc.DOLFIN_EPS  # tolerance for coordinate comparisons

    class Left(fc.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and abs(x[0] - xMin) < tol

    class Right(fc.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and abs(x[0] - xMax) < tol

    class Bottom(fc.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and abs(x[1] - zMin) < tol

    class Top(fc.SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and abs(x[1] - zMax) < tol

    # --------------------------------------
    # Initialize sub-domain instances
    # --------------------------------------
    left = Left()
    top = Top()
    right = Right()
    bottom = Bottom()
    # ----------------------------------------------
    # Initialize mesh function for boundary domains
    # ----------------------------------------------
    boundaries = fc.MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    domains = fc.MeshFunction("size_t", mesh, mesh.topology().dim())
    left.mark(boundaries, 3)
    top.mark(boundaries, 4)
    right.mark(boundaries, 5)
    bottom.mark(boundaries, 6)
    # ---------------------------------------
    # Define operator for speed vector theta
    # ---------------------------------------
    dtotal = Measure("dx")
    dircond = 1
    # ---------------------------------------
    # setting shape derivative weights
    # re-balancing sensibility to be greater at the bottom
    # ---------------------------------------
    wei_equation = '1.0e8*(pow(x[0] - 0.5, 16) + pow(x[1] - 0.325, 10))+100'
    wei = fc.Expression(str(wei_equation), degree=1)

    # Building the left hand side of the bi-linear system
    # to obtain the descendant direction from shape derivative
    if dircond < 4:
        bcF = [
            fc.DirichletBC(VF, (0, 0), boundaries, 3),
            fc.DirichletBC(VF, (0, 0), boundaries, 4),
            fc.DirichletBC(VF, (0, 0), boundaries, 5),
            fc.DirichletBC(VF, (0, 0), boundaries, 6)
        ]
    if dircond == 1:
        lhs = wei * alpha1 * inner(grad(theta), grad(csi)) * dtotal \
          + wei * alpha2 * inner(theta, csi) * dtotal
    #
    elif dircond == 2:
        lhs = alpha1 * inner(grad(theta), grad(csi)) * \
            dtotal + alpha2 * inner(theta, csi) * dtotal
    elif dircond == 3:
        lhs = inner(grad(theta), grad(csi)) * dtotal
    elif dircond == 5:
        lhs = inner(grad(theta), grad(csi)) * \
            dtotal + inner(theta, csi) * dtotal

    aV = fc.assemble(lhs)
    #
    if dircond < 4:
        for bc in bcF:
            bc.apply(aV)
    #
    # solver_V = fc.LUSolver(aV, "mumps")
    solver_V = fc.LUSolver(aV)
    # ------------------------------
    # Initialize Level set function
    # ------------------------------
    phi = fc.Function(V)
    phivec = phi.vector()
    phivalues = phivec.get_local()  # empty values
    my_first, my_last = V.dofmap().ownership_range()

    tabcoord = V.tabulate_dof_coordinates().reshape((-1, 2))

    unowned = V.dofmap().local_to_global_unowned()
    dofs = list(
        filter(
            lambda dof: V.dofmap().local_to_global_index(dof) not in unowned,
            [i for i in range(my_last - my_first)]))

    tabcoord = tabcoord[dofs]
    phivalues[:] = phi_mat.reshape(Nz * Nx)[dofs]  # assign values
    phivec.set_local(phivalues)
    phivec.apply('insert')

    cont = 0
    boundaries = fc.MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    domains = fc.MeshFunction("size_t", mesh, mesh.topology().dim())
    # -----------------------------
    # Define measures
    # -----------------------------
    dx = Measure('dx')(subdomain_data=domains)

    # -------------------------------
    # Define function Omega1
    # -------------------------------

    class Omega1(fc.SubDomain):
        def __init__(self) -> None:
            super(Omega1, self).__init__()

        def inside(self, x, on_boundary):
            return True if phi(x) <= 0 and x[0] >= xMin and x[0] <= xMax and x[
                1] >= zMin and x[1] <= zMax else False

    # instantiate variables
    eta = dmp(parameters)

    source = Source(parameters)
    FT = source.inject()

    phi_mat_old = np.zeros_like(phi_mat)
    vel_field_new = np.zeros_like(vel_field)
    theta1_mat = np.zeros((Nz * Nx))
    theta2_mat = np.zeros_like(theta1_mat)
    MainItEff = 0
    MainIt = 0
    stop_decision = 0
    st_mem_usage = 0.0
    adj_mem_usage = 0.0
    Jevaltotal = np.zeros((MainItMax))
    norm_theta = np.zeros((MainItMax))

    # path to recording phi function
    # path to recording misfit function
    if rank == 0:
        plot_mat(parameters, 'Damping', 'Damping function', eta)
        mkDirectory(parameters["path_phi"])
        mkDirectory(parameters["path_misfit"])

    comm.Barrier()
    # -------------------------------
    # Seismograms
    # -------------------------------
    wavesolver = WaveSolver(parameters, eta)
    start = time.time()
    d_send = np.empty((Nz, Nx, Nt), np.dtype('float'))
    d = wavesolver.measurements(d_send[0:Nz, 0:Nx, 0:Nt], synth_model,
                                FT[rank, 0:Nz, 0:Nx, 0:Nt], add_noise)
    seismograms = d[0, rec_index, 0:Nt].copy(order='C')
    end = time.time()

    # Plot Seismograms
    if PlotFields:
        print("{:.1f}s to build synthetic seismograms".format(end - start))
        plotMeasurements(parameters, seismograms, rank)
        if rank == 0:
            plot_displacement_field(parameters, d)

    sys.stdout.flush()
    del (d, d_send)
    ###################################################
    # Main Loop
    ###################################################
    gradshape = ShapeDerivative(parameters, csi, V, dtotal, seism_vel)
    while MainIt < MainItMax:
        # ----------------------------------------------
        # Initialize mesh function for boundary domains
        # ----------------------------------------------
        if MainIt > 0:
            vel_field = vel_field_new

        domains.set_all(0)
        omega1 = Omega1()
        omega1.mark(domains, 1)
        dx = Measure('dx')(subdomain_data=domains)

        u = np.empty((Nz, Nx, Nt), np.dtype('float'))
        P = np.empty((Nz, Nx, Nt), np.dtype('float'))

        if MainIt > 0:
            vel_field = vel_field_new
        # ------------------------------------
        # Compute STATE. u stands for displacement field
        # ------------------------------------
        start = time.time()
        u[0:Nz, 0:Nx, 0:Nt] = wavesolver.state(u[0:Nz, 0:Nx, 0:Nt], vel_field,
                                               FT[rank, 0:Nz, 0:Nx, 0:Nt])
        end = time.time()
        # ------------------------------------
        # Compute ADJOINT. P stands for the adjoint variable
        # ------------------------------------
        start1 = time.time()
        tr_u = u[0, rec_index, 0:Nt].copy(order='C')
        misfit = tr_u - seismograms
        P[0:Nz, 0:Nx, 0:Nt] = wavesolver.adjoint(P[0:Nz, 0:Nx, 0:Nt],
                                                 vel_field, misfit)
        end1 = time.time()
        comm.Barrier()
        print(
            '{:.1f}s to compute state and {:.1f}s to compute adjoint with {:d} shots. '
            .format(end - start, end1 - start1, n_shots))

        del (start, end, start1, end1)

        # Plot state/adjoint in 1st-iteration only
        if MainIt == 0 and PlotFields:
            if rank == 0:
                mkDirectory(path + 'initial_state_%03d/' % (n_shots))
                plotadjoint(parameters, P[0:Nz, 0:Nx, 0:Nt])
            folder_name = 'initial_state_%03d/' % (n_shots)
            plotstate(parameters, u[0:Nz, 0:Nx, 0:Nt], folder_name, rank)
            # plot_displacement_field(parameters, u[1, 0:Nz, 0:Nx, 0:Nt])
            st_mem_usage = (u.size * u.itemsize) / 1_073_741_824  # 1GB
            adj_mem_usage = (P.size * P.itemsize) / 1_073_741_824  # 1GB

        # Plotting reconstructions
        if rank == 0 and (MainItEff % 10 == 0
                          or stop_decision == stop_decision_limit - 1):
            plottype1(parameters, synth_model, phi_mat, cont)
            plottype2(parameters, synth_model, phi_mat, cont)
            plottype3(parameters, synth_model, phi_mat, MainIt, cont)
            plotcostfunction(parameters, Jevaltotal, MainItEff)
            plotnormtheta(parameters, norm_theta, MainItEff)
            np.save(path + 'last_phi_mat.npy', phi_mat)
            gnu_data(phi_mat, 'reconstruction.dat', parameters)

        plot_misfit(parameters, 'misfit', 'Misfit', misfit,
                    rank) if (MainItEff % 50 == 0 and PlotFields) else None

        # -------------------------
        # Compute Cost Function
        # -------------------------
        J_omega = np.zeros((1))
        l2_residual = np.sum(np.power(misfit, 2), axis=0)

        if MainIt == 0 and add_weight:
            weights = 1.0e-5

        comm.Reduce(simpson_rule(l2_residual[0:Nt], gc_t), J_omega, op=MPI.SUM)
        Jevaltotal[MainItEff] = 0.5 * (J_omega / weights)
        del (J_omega)
        # -------------------------
        # Evaluate shape derivative
        # -------------------------
        start = time.time()
        shapeder = (1.0 / weights) * gradshape.compute(u[0:Nz, 0:Nx, 0:Nt],
                                                       P[0:Nz, 0:Nx, 0:Nt], dx)
        # Build the rhs of bi-linear system
        shapeder = fc.assemble(shapeder)
        end = time.time()
        print('{}s to compute shape derivative.'.format(end - start))
        del (start, end)
        del (u, P)

        with open(path + "cost_function.txt", "a") as file_costfunction:
            file_costfunction.write('{:d} - {:.4e} \n'.format(
                MainItEff, Jevaltotal[MainItEff]))
        # ====================================
        # ---------- Line search -------------
        # ====================================
        if MainIt > 0 and Jevaltotal[MainItEff] > Jevaltotal[
                MainItEff - 1] and ls < ls_max:
            ls = ls + 1
            beta = beta * gamma
            phi_mat = phi_mat_old
            # ------------------------------------------------------------
            # Update level set function using the descent direction theta
            # ------------------------------------------------------------
            hj_input = [
                theta1_mat, theta2_mat, phi_mat, parameters, beta, MainItEff
            ]
            phi_mat = hamiltonjacobi(*hj_input)
            del (hj_input)
            ind = inside_shape(phi_mat)
            ind_c = np.ones_like(phi_mat) - ind
            vel_field_new = seism_vel[0] * ind + seism_vel[1] * ind_c

            phivec = phi.vector()
            phivalues = phivec.get_local()  # empty values
            my_first, my_last = V.dofmap().ownership_range()

            tabcoord = V.tabulate_dof_coordinates().reshape((-1, 2))
            set_trace()
            unowned = V.dofmap().local_to_global_unowned()
            dofs = list(
                filter(
                    lambda dof: V.dofmap().local_to_global_index(dof) not in
                    unowned, [i for i in range(my_last - my_first)]))

            tabcoord = tabcoord[dofs]
            phivalues[:] = phi_mat.reshape(Nz * Nx)[dofs]  # assign values
            phivec.set_local(phivalues)
            phivec.apply('insert')

        else:
            print("----------------------------------------------")
            print("Record in: {}".format(path))
            print("----------------------------------------------")
            print("ITERATION NUMBER (MainItEff)  : {:d}".format(MainItEff))
            print("ITERATION NUMBER (MainIt)  : {:d}".format(MainIt))
            print("----------------------------------------------")
            print("Grid Size                : {:d} x {:d}".format(Nx, Nz))
            print("State memory usage       : {:.4f} GB".format(st_mem_usage))
            print("Adjoint memory usage     : {:.4f} GB".format(adj_mem_usage))
            print("----------------------------------------------")
            print("Line search  iterations  : {:d}".format(ls))
            print("Step length beta         : {:.4e}".format(beta))
            if ls == ls_max:
                beta0 = max(beta0 * gamma2, 0.1 * beta0_init)
            if ls == 0:
                beta0 = min(beta0 / gamma2, 1.0)
            ls = 0
            MainItEff = MainItEff + 1
            beta = beta0  # /(0.999**MainIt)

            theta = fc.Function(VF)
            solver_V.solve(theta.vector(), -1.0 * shapeder)

            # ------------------------------------
            # Compute norm theta and grad(phi)
            # ------------------------------------
            mpi_comm = theta.function_space().mesh().mpi_comm()
            arraytheta = theta.vector().get_local()
            theta_gathered = mpi_comm.gather(arraytheta, root=0)

            # parei aqui !!!!!
            comm.Barrier()
            if rank == 0:
                set_trace()
                theta_vec = theta.vector()[fc.vertex_to_dof_map(VF)]
                theta1_mat = theta_vec[0:len(theta_vec):2].reshape(Nz, Nx)
                theta2_mat = theta_vec[1:len(theta_vec):2].reshape(Nz, Nx)
            norm_theta[MainItEff - 1] = np.sqrt(
                theta1_mat.reshape(Nz * Nx).dot(theta1_mat.reshape(Nx * Nz)) +
                theta2_mat.reshape(Nz * Nx).dot(theta2_mat.reshape(Nx * Nz)))
            max_gnp = np.sqrt(fc.assemble(dot(grad(phi), grad(phi)) * dtotal))
            print("Norm(grad(phi))          : {:.4e}".format(max_gnp))
            print("L2-norm of theta         : {:.4e}".format(
                norm_theta[MainItEff - 1]))
            print("Cost functional          : {:.4e}".format(
                Jevaltotal[MainItEff - 1]))

            # ------------------------------------------------------------
            # Update level set function using the descent direction theta
            # ------------------------------------------------------------
            phi_mat_old = phi_mat

            hj_input = [
                theta1_mat, theta2_mat, phi_mat, parameters, beta,
                MainItEff - 1
            ]

            phi_mat = hamiltonjacobi(*hj_input)

            del (hj_input)
            phi.vector()[:] = phi_mat.reshape(
                (Nz) * (Nx))[fc.dof_to_vertex_map(V)]
            ind = inside_shape(phi_mat)
            ind_c = np.ones_like(phi_mat) - ind
            vel_field_new = seism_vel[0] * ind + seism_vel[1] * ind_c

            # ----------------
            # Computing error
            # ----------------
            error_area = np.abs(chi1 - ind)
            relative_error = np.sum(error_area) / np.sum(chi0)
            print('relative error           : {:.3f}%'.format(100 *
                                                              relative_error))

            with open(path + "error.txt", "a") as text_file:
                text_file.write(f'{MainIt} {np.round(relative_error,3):>3}\n')

            # Plot actual phi function
            if MainIt % 50 == 0:
                plot_mat3D(parameters, 'phi_3D', phi_mat, MainIt)
                plot_countour(parameters, 'phi_contour', phi_mat, MainIt)
                phi_ind = '%03d_' % (MainIt)
                np.save(parameters["path_phi"] + phi_ind + 'phi.npy', phi_mat)

            # --------------------------------
            # Reinitialize level set function
            # --------------------------------
            if np.mod(MainItEff, 10) == 0:
                phi_mat = reinit(Nz, Nx, phi_mat)

            # ====================================
            # -------- Stopping criterion --------
            # ====================================
            if MainItEff > 5:
                stop0 = stop_coeff * (Jevaltotal[1] - Jevaltotal[2])
                stop1 = Jevaltotal[MainItEff - 2] - Jevaltotal[MainItEff - 1]
                if stop1 < stop0:
                    stop_decision = stop_decision + 1
                if stop_decision == stop_decision_limit:
                    MainIt = MainItMax + 1
                print("stop0                    : {:.4e}".format(stop0))
                print("stop1                    : {:.4e}".format(stop1))
            print("Stopping step            : {:d} of {:d}".format(
                stop_decision, stop_decision_limit))
            print("----------------------------------------------\n")
            cont += 1

        MainIt += 1

    return None
Exemplo n.º 7
0
    w_DMI = D * fe.inner(m, fe.curl(m))
    w_ani = -K * fe.inner(m, ea)**2
    w = w_Zeeman + w_exchange + w_DMI + w_ani
    return -1 / (mu0 * Ms) * fe.derivative(w * fe.dx, m)


m_init = fe.Constant((1, 0, 0))
m = fe.interpolate(m_init, V)

# Effective field
Heff_form = effective_field(m)

# Preassemble projection Matrix
Amat = fe.assemble(fe.dot(u, v) * fe.dx)

LU = fe.LUSolver()
LU.set_operator(Amat)


def compute_dmdt(m):
    """Convenience function that does all in one go"""

    # Assemble RHS
    b = fe.assemble(Heff_form)

    # Project onto Heff
    LU.solve(Heff.vector(), b)

    LLG = -gamma / (1 + alpha * alpha) * fe.cross(m, Heff) - alpha * gamma / (
        1 + alpha * alpha) * fe.cross(m, fe.cross(m, Heff))
CFL = 5.0
dt = CFL * hsize * hsize
T = 2.0
frequencySave = 100

# weak form
Left  = u/dt * uT * fn.dx + v/dt * vT * fn.dx \
        + c1 * fn.inner(fn.grad(u), fn.grad(uT)) * fn.dx \
        + c2 * fn.inner(fn.grad(v), fn.grad(vT)) * fn.dx

Right = uold * uT/dt * fn.dx + vold * vT/dt * fn.dx \
        + d * (a - uold + uold * uold * vold) * uT * fn.dx \
        + d * (b - uold * uold * vold) * vT * fn.dx

AA = fn.assemble(Left)
solver = fn.LUSolver(AA)
solver.parameters["reuse_factorization"] = True

# time loop
inc = 0

while (t <= T):

    print "t =", t

    # solve
    BB = fn.assemble(Right)
    solver.solve(Sol.vector(), BB)

    # output to file
    u, v = Sol.split()
Exemplo n.º 9
0
def construct_solver(bilinear_form, boundary_conditions):
    matrix = fenics.assemble(bilinear_form)
    apply_boundary_conditions(matrix, boundary_conditions)
    return fenics.LUSolver(matrix)
Exemplo n.º 10
0
#Tiempos intermedio entre tn y tn+1 utilizando modelo alfa generalizado
def avg(x_old, x_new, alpha):
    return alpha * x_old + (1 - alpha) * x_new


#Formulación variacional
a_new = update_a(du, u_old, v_old, a_old, ufl=True)
v_new = update_v(a_new, u_old, v_old, a_old, ufl=True)
res = m(avg(a_old, a_new, alpha_m), w) + c(avg(v_old, v_new, alpha_f), w) + k(
    avg(u_old, du, alpha_f), w) - Wext(w)
a_form = fnc.lhs(res)
L_form = fnc.rhs(res)

#Solvers (veremos luego)
K, res = fnc.assemble_system(a_form, L_form, bc)
solver = fnc.LUSolver(K, 'default')  #"mumps")
solver.parameters["symmetric"] = True

# We now initiate the time stepping loop. We will keep track of the beam vertical tip
# displacement over time as well as the different parts of the system total energy. We
# will also compute the stress field and save it, along with the displacement field, in
# a ``XDMFFile``.
# The option `flush_ouput` enables to open the result file before the loop is finished,
# the ``function_share_mesh`` option tells that only one mesh is used for all functions
# of a given time step (displacement and stress) while the ``rewrite_function_mesh`` enforces
# that the same mesh is used for all time steps. These two options enables writing the mesh
# information only once instead of :math:`2N_{steps}` times::

# Time-stepping
time = np.linspace(0, T, Nsteps + 1)
u_tip = np.zeros((Nsteps + 1, ))
    # Compare timing of fenics solve vs scipy solve
    import scipy.sparse.linalg as spla

    t = time()
    solve_A_scipy = spla.factorized(A_scipy)
    scipy_factorization_time = time() - t
    print('scipy_factorization_time=', scipy_factorization_time)

    t = time()
    x_numpy = solve_A_scipy(b_numpy)
    scipy_solve_time = time() - t
    print('scipy_solve_time=', scipy_solve_time)

    t = time()
    solve_A_fenics = fenics.LUSolver(A_fenics)
    fenics_factorization_time = time() - t
    print('fenics_factorization_time=', fenics_factorization_time)

    x = fenics.Function(V)

    t = time()
    solve_A_fenics.solve(x.vector(), b_fenics)
    fenics_first_solve_time = time() - t
    print('fenics_first_solve_time=', fenics_first_solve_time)

    x2 = fenics.Function(V)

    t = time()
    solve_A_fenics.solve(x2.vector(), b_fenics)
    fenics_second_solve_time = time() - t