def __init__(self, mesh, Vh_STATE, x0):
        """
        Constructor.
        INPUTS:
        
        - mesh: the mesh
        - Vh_STATE: the finite element space for the state variable
        - x0: location at which we want to compute the jet-thickness
        """

        Vh_help = dl.FunctionSpace(mesh, "CG", 1)
        xfun = dl.interpolate(dl.Expression("x[0]", degree=1), Vh_help)
        x_coord = xfun.vector().gather_on_zero()

        mpi_comm = mesh.mpi_comm()
        rank = dl.MPI.rank(mpi_comm)
        nproc = dl.MPI.size(mpi_comm)

        # round x0 so that it is aligned with the mesh
        if nproc > 1:
            from mpi4py import MPI
            comm = MPI.COMM_WORLD
            if rank == 0:
                idx = (np.abs(x_coord - x0)).argmin()
                self.x0 = x_coord[idx]
            else:
                self.x0 = None

            self.x0 = comm.bcast(self.x0, root=0)
        else:
            idx = (np.abs(x_coord - x0)).argmin()
            self.x0 = x_coord[idx]

        line_segment = dl.AutoSubDomain(lambda x: dl.near(x[0], self.x0))
        markers_f = dl.FacetFunction("size_t", mesh)
        markers_f.set_all(0)
        line_segment.mark(markers_f, 1)
        dS = dl.dS[markers_f]

        x_test = dl.TestFunctions(Vh_STATE)
        u_test = x_test[0]

        e1 = dl.Constant(("1.", "0."))

        self.int_u = dl.assemble(dl.avg(dl.dot(u_test, e1)) * dS(1))
        #self.u_cl = dl.assemble( dl.dot(u_test,e1)*dP(1) )

        self.u_cl = dl.Function(Vh_STATE).vector()
        ps = dl.PointSource(Vh_STATE.sub(0).sub(0), dl.Point(self.x0, 0.), 1.)
        ps.apply(self.u_cl)

        scaling = self.u_cl.sum()
        if np.abs(scaling - 1.) > 1e-6:
            print scaling
            raise ValueError()

        self.state = dl.Function(Vh_STATE).vector()
        self.help = dl.Function(Vh_STATE).vector()
Exemple #2
0
def fem_pts(conductivity, pos_list, save_dest, ele_list=None, sel_idx=None):
    NPYSave = False
    HDF5Save = False
    if save_dest.find('.h5') > -1:
        HDF5Save = True
        dump_file = d.HDF5File(d.mpi_comm_world(), save_dest, 'w')
    elif save_dest.find('.npy') > -1:
        if not ele_list:
            print('Expecting ele_list argument')
        else:
            NPYSave = True
    else:
        print('Only .h5 (entire mesh space), .npy (known ele_pos) supported')
        print('Will not save anything this time')
    if not sel_idx:
        sel_idx = range(len(pos_list))
    print('On this process no. pt. srcs = ', len(sel_idx))
    mesh, subdomain, boundaries = meshes.load_meshes()
    sigma = sigma_tensor(mesh, conductivity=conductivity)
    print('Done loading meshes and conductivity')
    V = d.FunctionSpace(mesh, "CG", 2)
    v = d.TestFunction(V)
    u = d.TrialFunction(V)
    dx = d.Measure("dx")(subdomain_data=subdomain)
    # ds = d.Measure("ds")(subdomain_data=boundaries)
    a = d.inner(sigma * d.grad(u), d.grad(v)) * dx
    L = d.Constant(0) * v * dx()
    A = d.assemble(a)
    # Surface of the grnd ele = 1030
    bc = d.DirichletBC(V, d.Constant(0), boundaries, 1030)

    for curr_idx in sel_idx:
        solver = set_solver()
        phi = d.Function(V)
        x = phi.vector()
        print('Started computing for,at: ', curr_idx, pos_list[curr_idx])
        b = d.assemble(L)
        bc.apply(A, b)
        xx, yy, zz = pos_list[curr_idx]
        point = d.Point(xx, yy, zz)
        delta = d.PointSource(V, point, 1.)
        delta.apply(b)
        solver.solve(A, x, b)
        # file = d.File("pots_anis.pvd")
        # file << phi
        if HDF5Save:
            dump_file.write(x.array(), str(curr_idx))
            dump_file.flush()
        if NPYSave:
            vals = extract_pots(phi, np.array(ele_list))
            np.save(save_dest, vals)
        print('Finished computing for :', curr_idx)
    return
Exemple #3
0
 def onclick(event):
     if print_point:
         print('(', event.xdata, ',', event.ydata, ')')
     delta_p = dl.PointSource(function_space_V, dl.Point(event.xdata, event.ydata), 1.0)
     if event.button == 3:
         point_source_dual_vector[:] = 0.
     delta_p.apply(point_source_dual_vector)
     Adelta.vector()[:] = apply_A(point_source_dual_vector)
     plt.clf()
     c = dl.plot(Adelta)
     plt.colorbar(c)
     plt.title('left click adds points, right click resets')
     plt.draw()
Exemple #4
0
 def ptsrc(self,u,ord=1):
     """
     Point source of (ord) order derivative of data-misfit function wrt. the solution u.
     """
     assert ord in [1,2], 'Wrong order!'
     u_vec = self._extr_soloc(u)
     # define PointSource similar to boundary function, but PointSource is applied to (rhs) vector and is limited to scalar FunctionSpace
     dfun_vec = u_vec
     if ord==1:
         dfun_vec -= self.obs
     dfun_vec *= self.prec
     dirac = [df.PointSource(self.pde.W.sub(0),df.Point(p),f) for (p,f) in zip(self.loc,dfun_vec)] # fails in 1.6.0 (mac app) possibly due to swig bug in numpy.i (already fixed in numpy 1.10.2) of the system numpy 1.8.0rc1
     return dirac
Exemple #5
0
    def accountPointSource(self):
        #-----------------------------------------------------------------------------------
        componentIndex = {'real': 0, 'imag': 1}
        for sourceComponent in ('real', 'imag'):
            if self.sourceOpt[sourceComponent]['choice'] == 'pointSource':
                pointSourceMag = self.sourceOpt[sourceComponent][
                    'pointSourceMag']
                pointSourceLoc = self.sourceOpt[sourceComponent][
                    'pointSourceLoc']
                for funSpaceComponent in ('real', 'imag'):
                    if sourceComponent == 'imag' and funSpaceComponent == 'imag':
                        pointSourceMag = -pointSourceMag
                    PS = df.PointSource(self.V.sub(componentIndex[funSpaceComponent]),\
                                 df.Point(pointSourceLoc),pointSourceMag)
                    PS.apply(self.rhsVec)

        return
Exemple #6
0
# Define function space and basis functions

# This corresponds to Neumann boundary conditions zero, i.e. all outer boundaries are insulating.
L = df.Constant(0) * v * dx

# Define Dirichlet boundary conditions at left and right boundaries
bcs = [df.DirichletBC(V, 0.0, boundaries, 1)]

for t_idx in range(num_tsteps):

    print("Time step {} of {}".format(t_idx, num_tsteps))
    phi = df.Function(V)
    A = df.assemble(a)
    b = df.assemble(L)

    [bc.apply(A, b) for bc in bcs]

    # Adding point sources from neural simulation
    for s_idx, s_pos in enumerate(source_pos):

        point = df.Point(s_pos[0], s_pos[1], s_pos[2])
        delta = df.PointSource(V, point, imem[s_idx, t_idx])
        delta.apply(b)

    df.solve(A, phi.vector(), b, 'cg', "ilu")

    # df.File(join(out_folder, "phi_t_vec_{}.xml".format(t_idx))) << phi
    np.save(join(out_folder, "phi_t_vec_{}.npy".format(t_idx)), phi.vector())

    plot_FEM_results(phi, t_idx)
Exemple #7
0
def run_model(function_space,
              kappa,
              forcing,
              init_condition,
              dt,
              final_time,
              boundary_conditions=None,
              second_order_timestepping=False,
              exact_sol=None,
              velocity=None,
              point_sources=None,
              intermediate_times=None):
    """
    Use implicit euler to solve transient advection diffusion equation

    du/dt = grad (k* grad u) - vel*grad u + f

    WARNINGarningW: when point sources solution changes significantly when mesh is varied
    """
    mesh = function_space.mesh()

    time_independent_boundaries = False
    if boundary_conditions == None:
        bndry_obj = dl.CompiledSubDomain("on_boundary")
        boundary_conditions = [['dirichlet', bndry_obj, dl.Constant(0)]]
        time_independent_boundaries = True

    num_bndrys = len(boundary_conditions)
    boundaries = mark_boundaries(mesh, boundary_conditions)
    dirichlet_bcs = collect_dirichlet_boundaries(function_space,
                                                 boundary_conditions,
                                                 boundaries)

    # To express integrals over the boundary parts using ds(i), we must first
    # redefine the measure ds in terms of our boundary markers:
    ds = dl.Measure('ds', domain=mesh, subdomain_data=boundaries)
    dx = dl.Measure('dx', domain=mesh)

    # Variational problem at each time
    u = dl.TrialFunction(function_space)
    v = dl.TestFunction(function_space)

    # Previous solution
    if hasattr(init_condition, 't'):
        assert init_condition.t == 0
    u_1 = dl.interpolate(init_condition, function_space)

    if not second_order_timestepping:
        theta = 1
    else:
        theta = 0.5

    if hasattr(forcing, 't'):
        forcing_1 = copy_expression(forcing)
    else:
        forcing_1 = forcing

    def steady_state_form(u, v, f):
        F = kappa * dl.inner(dl.grad(u), dl.grad(v)) * dx
        F -= f * v * dx
        if velocity is not None:
            F += dl.dot(velocity, dl.grad(u)) * v * dx
        return F

    F =  u*v*dx-u_1*v*dx + dt*theta*steady_state_form(u,v,forcing) + \
         dt*(1.-theta)*steady_state_form(u_1,v,forcing_1)
    a, L = dl.lhs(F), dl.rhs(F)

    # a = u*v*dx + theta*dt*kappa*dl.inner(dl.grad(u), dl.grad(v))*dx
    # L = (u_1 + dt*theta*forcing)*v*dx

    # if velocity is not None:
    #     a += theta*dt*v*dl.dot(velocity,dl.grad(u))*dx

    # if second_order_timestepping:
    #     L -= (1-theta)*dt*dl.inner(kappa*dl.grad(u_1), dl.grad(v))*dx
    #     L += (1-theta)*dt*forcing_1*v*dx

    #     if velocity is not None:
    #         L -= (1-theta)*dt*(v*dl.dot(velocity,dl.grad(u_1)))*dx

    beta_1_list = []
    alpha_1_list = []
    for ii in range(num_bndrys):
        if (boundary_conditions[ii][0] == 'robin'):
            alpha = boundary_conditions[ii][3]
            a += theta * dt * alpha * u * v * ds(ii)
            if second_order_timestepping:
                if hasattr(alpha, 't'):
                    alpha_1 = copy_expression(alpha)
                    alpha_1_list.append(alpha_1)
                else:
                    alpha_1 = alpha
                L -= (1 - theta) * dt * alpha_1 * u_1 * v * ds(ii)

        if ((boundary_conditions[ii][0] == 'robin')
                or (boundary_conditions[ii][0] == 'neumann')):
            beta = boundary_conditions[ii][2]
            L -= theta * dt * beta * v * ds(ii)
            if second_order_timestepping:
                if hasattr(beta, 't'):
                    beta_1 = copy_expression(beta)
                    beta_1_list.append(beta_1)
                else:
                    # boundary condition is constant in time
                    beta_1 = beta
                L -= (1 - theta) * dt * beta_1 * v * ds(ii)

    if time_independent_boundaries:
        # TODO this can be used if dirichlet and robin conditions are not
        # time dependent.
        A = dl.assemble(a)
        for bc in dirichlet_bcs:
            bc.apply(A)
        solver = dl.LUSolver(A)
        #solver.parameters["reuse_factorization"] = True
    else:
        solver = None

    u_2 = dl.Function(function_space)
    u_2.assign(u_1)
    t = 0.0

    dt_tol = 1e-12
    n_time_steps = 0
    if intermediate_times is not None:
        intermediate_u = []
        intermediate_cnt = 0
        # assert in chronological order
        assert np.allclose(intermediate_times, np.array(intermediate_times))
        assert np.all(intermediate_times < final_time)

    while t < final_time - dt_tol:
        # Update current time
        t += dt
        forcing.t = t
        forcing_1.t = t - dt

        # set current time for time varying boundary conditions
        for ii in range(num_bndrys):
            if hasattr(boundary_conditions[ii][2], 't'):
                boundary_conditions[ii][2].t = t

        # set previous time for time varying boundary conditions when
        # using second order timestepping. lists will be empty if using
        # first order timestepping
        for jj in range(len(beta_1_list)):
            beta_1_list[jj].t = t - dt
        for jj in range(len(alpha_1_list)):
            alpha_1_list[jj].t = t - dt

        #A, b = dl.assemble_system(a, L, dirichlet_bcs)
        #for bc in dirichlet_bcs:
        #    bc.apply(A,b)
        if boundary_conditions is not None:
            A = dl.assemble(a)
            for bc in dirichlet_bcs:
                bc.apply(A)

        b = dl.assemble(L)
        for bc in dirichlet_bcs:
            bc.apply(b)

        if point_sources is not None:
            ps_list = []
            for ii in range(len(point_sources)):
                point, expr = point_sources[ii]
                ps_list.append((dl.Point(point[0], point[1]), expr(t)))
            ps = dl.PointSource(function_space, ps_list)
            ps.apply(b)

        if solver is None:
            dl.solve(A, u_2.vector(), b)
        else:
            solver.solve(u_2.vector(), b)

        #print ("t =", t, "end t=", final_time)

        # Update previous solution
        u_1.assign(u_2)
        # import matplotlib.pyplot as plt
        # plt.subplot(131)
        # pp=dl.plot(u_1)
        # plt.subplot(132)
        # dl.plot(forcing,mesh=mesh)
        # plt.subplot(133)
        # dl.plot(forcing_1,mesh=mesh)
        # plt.colorbar(pp)
        # plt.show()

        # compute error
        if exact_sol is not None:
            exact_sol.t = t
            error = dl.errornorm(exact_sol, u_2)
            print('t = %.2f: error = %.3g' % (t, error))
            #dl.plot(exact_sol,mesh=mesh)
            #plt.show()

        t = min(t, final_time)
        if (intermediate_times is not None
                and intermediate_cnt < intermediate_times.shape[0]
                and t >= intermediate_times[intermediate_cnt]):
            #save solution closest to intermediate time
            u_t = dl.Function(function_space)
            u_t.assign(u_2)
            intermediate_u.append(u_t)
            intermediate_cnt += 1
        n_time_steps += 1
    #print ("t =", t, "end t=", final_time,"# time steps", n_time_steps)

    if intermediate_times is None:
        return u_2
    else:
        return intermediate_u + [u_2]
def simulate_FEM():

    import dolfin as df
    df.parameters['allow_extrapolation'] = False

    # Define mesh
    mesh = df.Mesh(join(mesh_folder, "{}.xml".format(mesh_name)))
    subdomains = df.MeshFunction("size_t", mesh, join(mesh_folder,
                          "{}_physical_region.xml".format(mesh_name)))
    boundaries = df.MeshFunction("size_t", mesh, join(mesh_folder,
                          "{}_facet_region.xml".format(mesh_name)))

    print("Number of cells in mesh: ", mesh.num_cells())

    np.save(join(out_folder, "mesh_coordinates.npy"), mesh.coordinates())

    sigma_vec = df.Constant(sigma)

    V = df.FunctionSpace(mesh, "CG", 2)
    v = df.TestFunction(V)
    u = df.TrialFunction(V)

    ds = df.Measure("ds", domain=mesh, subdomain_data=boundaries)
    dx = df.Measure("dx", domain=mesh, subdomain_data=subdomains)

    a = df.inner(sigma_vec * df.grad(u), df.grad(v)) * dx(1)

    # This corresponds to Neumann boundary conditions zero, i.e.
    # all outer boundaries are insulating.
    L = df.Constant(0) * v * dx

    # Define Dirichlet boundary conditions outer cylinder boundaries (ground)
    bcs = [df.DirichletBC(V, 0.0, boundaries, 1)]

    for t_idx in range(num_tsteps):

        f_name = join(out_folder, "phi_xz_t_vec_{}.npy".format(t_idx))
        # if os.path.isfile(f_name):
        #     print("skipping ", f_name)
        #     continue

        print("Time step {} of {}".format(t_idx, num_tsteps))
        phi = df.Function(V)
        A = df.assemble(a)
        b = df.assemble(L)

        [bc.apply(A, b) for bc in bcs]

        # Adding point sources from neural simulation
        for s_idx, s_pos in enumerate(source_pos):

            point = df.Point(s_pos[0], s_pos[1], s_pos[2])
            delta = df.PointSource(V, point, imem[s_idx, t_idx])
            delta.apply(b)

        df.solve(A, phi.vector(), b, 'cg', "ilu")

        # df.File(join(out_folder, "phi_t_vec_{}.xml".format(t_idx))) << phi
        # np.save(join(out_folder, "phi_t_vec_{}.npy".format(t_idx)), phi.vector())

        plot_and_save_simulation_results(phi, t_idx)
Exemple #9
0
    def run(self, species="Oxygen", increment=0):

        # Specify the test/trial function space

        df.set_log_active(False)
        V = df.FunctionSpace(self.mesh, "Lagrange", 1)

        # Specify the boundary conditions, Dirichlet on all domain faces
        def u0_boundary(x, on_boundary):
            return on_boundary

        # Define the problem
        u = df.TrialFunction(V)
        v = df.TestFunction(V)
        if species == "Oxygen":
            bc = df.DirichletBC(V, df.Constant(1), u0_boundary)
            f = df.Constant(0.0)
            a = self.Dc * df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx
            L = f * v * df.dx
        elif species == "Factor":
            bc = df.DirichletBC(V, df.Constant(0), u0_boundary)
            f = df.Constant(0)
            a = (self.decayRate * u * v + self.Dv *
                 df.inner(df.nabla_grad(u), df.nabla_grad(v))) * df.dx
            L = f * v * df.dx

        # Assemble the system
        A, b = df.assemble_system(a, L, bc)

        if species == "Oxygen":

            # Add vessel source terms
            vesselSources = self.sources[1]
            for eachSource in vesselSources:
                location = [
                    point - self.spacing / 2.0 for point in eachSource[0]
                ]
                if self.extents[2] > 1:
                    delta = df.PointSource(
                        V, df.Point(location[0], location[1], location[2]),
                        self.permeability * eachSource[1])
                else:
                    delta = df.PointSource(V, df.Point(location[0],
                                                       location[1]),
                                           self.permeability * eachSource[1])
                try:
                    delta.apply(b)
                except:
                    pass

            # Add cell sink terms
            cellSources = self.sources[0]
            for eachSource in cellSources:
                location = [
                    point - self.spacing / 2.0 for point in eachSource[0]
                ]
                if self.extents[2] > 1:
                    delta = df.PointSource(
                        V, df.Point(location[0], location[1], location[2]),
                        -self.consumptionRate * eachSource[1])
                else:
                    delta = df.PointSource(
                        V, df.Point(location[0], location[1]),
                        -self.consumptionRate * eachSource[1])
                try:
                    delta.apply(b)
                except:
                    pass

        elif species == "Factor":
            # Add cell source terms
            cellSources = self.sources[0]
            for eachSource in cellSources:
                location = [
                    point - self.spacing / 2.0 for point in eachSource[0]
                ]
                if self.extents[2] > 1:
                    delta = df.PointSource(
                        V, df.Point(location[0], location[1], location[2]),
                        self.factorSensitvity * eachSource[1])
                else:
                    delta = df.PointSource(
                        V, df.Point(location[0], location[1]),
                        self.factorSensitvity * eachSource[1])
                try:
                    delta.apply(b)
                except:
                    pass

        # Set up solution vector
        u = df.Function(V)
        U = u.vector()

        # Set up and run solver
        solver = df.KrylovSolver("cg", "ilu")
        solver.solve(A, U, b)

        self.result = []
        for eachEntry in self.sources[0]:
            location = [point - self.spacing / 2.0 for point in eachEntry[0]]
            if self.extents[2] <= 1:
                location = location[:2]
            try:
                result = u(location)
            except:
                if species == "Oxygen":
                    result = 1.0
                else:
                    result = 0.0
            self.result.append(result)

        self.write_output(species, increment)
        return self.result
Exemple #10
0
def solve_adjoint(evo, control, ps_magnitude, target_point, a, V, j):
    '''Calculates the solution to the adjoint problem.

    The solution to the adjoint equation is calculated using the explicitly
    given evolution (solution to the forward problem) and the control.

    For better understanding of the indeces see docs/indexing-diagram.txt.

    Parameters: OUTDATED
        V: dolfin.FunctionSpace
            The FEM space of the problem being solved.
        evo: ndarray
            The coefficients of the solution to the corresponding forward
            problem in the basis of the space V (see solve_forward).
        control: ndarray
            The laser power profile.
        beta_welding
        target_point: dolfin.Point
        threshold_temp
        penalty_term_combined

    Returns:
        evo_adj: ndarray
            The coefficients of the calculated adjoint solution in the basis of
            the space V.
            
    '''

    # initialize state functions
    theta_km1 = dolfin.Function(V)  # stands for theta[k-1]
    theta_k = dolfin.Function(V)    # stands for theta[k]
    theta_kp1 = dolfin.Function(V)  # stands for theta[k+1]

    # initialize adjoint state functions
    p_km1 = dolfin.Function(V)      # stands for p[k-1]
    p_k = dolfin.Function(V)        # stands for p[k]

    # FEM equation setup
    p = dolfin.TrialFunction(V)     # stands for unknown p[k-1]
    v = dolfin.TestFunction(V)

    Nt = len(control)
    evo_adj = np.zeros((Nt+1, len(V.dofmap().dofs())))

    # preparing for the first iteration
    theta_k.vector().set_local(evo[Nt])

    # solve backward, i.e. p_k -> p = p_km1, k = Nt, Nt-1, Nt-2, ..., 1
    for k in range(Nt, 0, -1):
        theta_km1.vector().set_local(evo[k-1])

        F = a(theta_km1, theta_k, p, control[k-1])\
          + j(k-1, theta_km1, theta_k)

        if k < Nt:
            F += a(theta_k, theta_kp1, p_k, control[k])\
               + j(k, theta_k, theta_kp1)


        dF = dolfin.derivative(F, theta_k, v)
        
        # sometimes rhs(dF) is void which leads to a ValueError
        try:
            A, b = dolfin.assemble_system(dolfin.lhs(dF), dolfin.rhs(dF))
        except ValueError:
            A, b = dolfin.assemble_system(dolfin.lhs(dF), Constant(0)*v*dx)

        # apply welding penalty as a point source
        point_source = dolfin.PointSource(V, target_point, ps_magnitude[k-1])
        point_source.apply(b)

        dolfin.solve(A, p_km1.vector(), b)
 
        evo_adj[k-1] = p_km1.vector().get_local()

        # preparing for the next iteration
        p_k.assign(p_km1)
        theta_kp1.assign(theta_k)
        theta_k.assign(theta_km1)

    return evo_adj