예제 #1
0
def image2fct2D(image_select):
    """
    This function converts a 2D slice of a 3D SimpleITK image instance into a 2D FEniCS function.
    We use this function to extract a 2D 'labelmap' from a 3D segmentation image.
    :param image_select: slice id in z direction
    :return: instance of fenics.Function()
    """
    image_select_np = sitk.GetArrayFromImage(image_select)
    image_select_np_flat = image_select_np.flatten()
    origin = image_select.GetOrigin()
    spacing = image_select.GetSpacing()
    height = image_select.GetHeight()
    width = image_select.GetWidth()
    depts = image_select.GetDepth()

    # construct rectangular mesh with dofs on pixels
    p1 = fenics.Point(origin[0], origin[1])
    p2 = fenics.Point(origin[0] + spacing[0] * width,
                      origin[1] + spacing[1] * height)
    nx = int(width - 1)
    ny = int(height - 1)
    fenics.parameters["reorder_dofs_serial"] = False
    mesh_image = fenics.RectangleMesh(p1, p2, nx, ny)
    n_components = image_select.GetNumberOfComponentsPerPixel()
    if n_components == 1:
        V = fenics.FunctionSpace(mesh_image, "CG", 1)
    else:
        V = fenics.VectorFunctionSpace(mesh_image, "CG", 1)
    gdim = mesh_image.geometry().dim()
    coords = V.tabulate_dof_coordinates().reshape((-1, gdim))
    f_img = fenics.Function(V)
    f_img.vector()[:] = image_select_np_flat
    fenics.parameters["reorder_dofs_serial"] = True
    return f_img
예제 #2
0
def create_fenics_function_from_image_quick(image):
    origin, size, spacing, extent, dim, vdim = get_measures_from_image(image)
    # fenics expects number of elements as input argument to Rectangle/BoxMesh
    # i.e., n_nodes - 1
    size_new = size - np.ones_like(size, dtype=int)
    # construct rectangular/box mesh with dofs on pixels
    p_min = fenics.Point(extent[0, :])
    p_max = fenics.Point(extent[1, :])
    if dim == 2:
        mesh_image = fenics.RectangleMesh(p_min, p_max, *list(size_new))
    elif dim == 3:
        mesh_image = fenics.BoxMesh(p_min, p_max, *list(size_new))
    # define value dimensionality
    if vdim == 1:
        fenics.parameters["reorder_dofs_serial"] = False
        V = fenics.FunctionSpace(mesh_image, "CG", 1)
    else:
        fenics.parameters["reorder_dofs_serial"] = True
        V = fenics.VectorFunctionSpace(mesh_image, "CG", 1)
    # get and assign values
    image_np = sitk.GetArrayFromImage(image)
    image_np_flat = image_np.flatten()
    f_img = fenics.Function(V)
    f_img.vector()[:] = image_np_flat
    fenics.parameters["reorder_dofs_serial"] = False
    return f_img
예제 #3
0
def add_noise(function, noise_level):
    noise = fenics.Function(function.function_space())
    noise.vector()[:] = noise_level * np.random.randn(
        len(function.function_space().dofmap().dofs()))
    fun_with_noise = fenics.project(function + noise,
                                    function.function_space(),
                                    annotate=False)
    return fun_with_noise
def load_function_from_xdmf(path_to_file, functionname, functionspace, step=0):
    mpi_comm_world = fenics.mpi_comm_world()
    function_file = fenics.XDMFFile(mpi_comm_world, path_to_file)
    mesh = fenics.Mesh()
    function_file.read(mesh)
    f = fenics.Function(functionspace)
    function_file.read_checkpoint(f, functionname, step)
    return f
예제 #5
0
def read_function_hdf5(name, functionspace, path_to_file):
    if os.path.exists(path_to_file):
        f = fenics.Function(functionspace)
        hdf = fenics.HDF5File(functionspace.mesh().mpi_comm(), path_to_file,
                              "r")
        attr = hdf.attributes(name)
        #nsteps = attr['count']
        dataset = name + "/vector_0"
        hdf.read(f, dataset)
        hdf.close()
        return f
예제 #6
0
def create_fenics_function_from_image(image):
    origin, size, spacing, extent, dim, vdim = get_measures_from_image(image)
    # fenics expects number of elements as input argument to Rectangle/BoxMesh
    # i.e., n_nodes - 1
    size_new = size - np.ones_like(size, dtype=int)
    # construct rectangular/box mesh with dofs on pixels
    p_min = fenics.Point(extent[0, :])
    p_max = fenics.Point(extent[1, :])
    if dim == 2:
        mesh_image = fenics.RectangleMesh(p_min, p_max, *list(size_new))
    elif dim == 3:
        mesh_image = fenics.BoxMesh(p_min, p_max, *list(size_new))
    # define value dimensionality
    if vdim == 1:
        V = fenics.FunctionSpace(mesh_image, "CG", 1)
    else:
        V = fenics.VectorFunctionSpace(mesh_image, "CG", 1, dim=2)
    # get and assign values
    f_img = fenics.Function(V)
    coord_array, value_array = get_coord_value_array_for_image(image,
                                                               flat=True)
    unasigned_coords = assign_values_to_fenics_function(
        f_img, coord_array, value_array)
    return f_img
    def _setup_problem(self, u_previous):
        dim = self.geometric_dimension
        dx = self.subdomains.dx
        ds = self.subdomains.ds
        dsn = self.subdomains.dsn

        mu = mle.compute_mu(self.params.E, self.params.poisson)
        lmbda = mle.compute_lambda(self.params.E, self.params.poisson)
        diff_const = self.params.diffusion
        prolif_rate = self.params.proliferation
        coupling = self.params.coupling

        # # This is the mechanical body force
        if not hasattr(self,'body_force'):
            self.body_force = fenics.Constant(zeros(dim))

        # This is the RD source term
        if not hasattr(self, 'source_term'):
            self.source_term = fenics.Constant(0.0)

        du = fenics.TrialFunction(self.functionspace.function_space)
        v0, v1 = fenics.TestFunctions(self.functionspace.function_space)
        self.solution = fenics.Function(self.functionspace.function_space, name='solution_function')
        self.solution.label = 'solution_function'

        sol0, sol1 = fenics.split(self.solution)
        u_previous0, u_previous1 = fenics.split(u_previous)

        self.logger.info("    - Using non-linear solver")

        dt = fenics.Constant(float(self.params.sim_time_step))

        F_m = fenics.inner(mle.compute_stress(sol0, mu, lmbda), mle.compute_strain(v0)) * dx \
              - fenics.inner(mle.compute_stress(v0, mu, lmbda), mle.compute_growth_induced_strain(sol1, coupling, dim)) * dx \
              - fenics.inner(self.body_force, v0) * dx \
              - self.bcs.implement_von_neumann_bc(v0, subspace_id=0)  # integral over ds already included

        F_rd = sol1 * v1 * dx \
               + dt * diff_const * fenics.inner(fenics.grad(sol1), fenics.grad(v1)) * dx \
               - u_previous1 * v1 * dx \
               - dt * mrd.compute_growth_logistic(sol1, prolif_rate, 1.0) * v1 * dx \
               - dt * self.source_term * v1 * dx \
               - dt * self.bcs.implement_von_neumann_bc(diff_const * v1, subspace_id=1)  # integral over ds already included

        F = F_m + F_rd

        J = fenics.derivative(F, self.solution, du)

        problem = fenics.NonlinearVariationalProblem(F, self.solution, bcs=self.bcs.dirichlet_bcs, J=J)
        solver = fenics.NonlinearVariationalSolver(problem)
        prm = solver.parameters
        prm['nonlinear_solver'] = 'snes'
        prm['snes_solver']['report'] = False
        # prm.snes_solver.linear_solver = "lu"
        # prm.snes_solver.maximum_iterations = 20
        # prm.snes_solver.report = True
        # prm.snes_solver.error_on_nonconvergence = False
        # prm.snes_solver.preconditioner = 'amg'
        # prm = solver.parameters.newton_solver  # short form -> Newton Solver
        # prm.absolute_tolerance = 1E-11
        # prm.relative_tolerance = 1E-8
        # prm.maximum_iterations = 1000
        self.solver = solver
예제 #8
0
    def _setup_problem(self, u_previous):
        dx = self.subdomains.dx
        ds = self.subdomains.ds
        dsn = self.subdomains.dsn
        # Parameters
        mu_GM = mle.compute_mu(self.params.E_GM, self.params.nu_GM)
        lmbda_GM = mle.compute_lambda(self.params.E_GM, self.params.nu_GM)
        mu_WM = mle.compute_mu(self.params.E_WM, self.params.nu_WM)
        lmbda_WM = mle.compute_lambda(self.params.E_WM, self.params.nu_WM)
        mu_CSF = mle.compute_mu(self.params.E_CSF, self.params.nu_CSF)
        lmbda_CSF = mle.compute_lambda(self.params.E_CSF, self.params.nu_CSF)
        mu_VENT = mle.compute_mu(self.params.E_VENT, self.params.nu_VENT)
        lmbda_VENT = mle.compute_lambda(self.params.E_VENT,
                                        self.params.nu_VENT)
        mu_OUT = mle.compute_mu(10E3, 0.45)
        lmbda_OUT = mle.compute_lambda(10E3, 0.45)
        coupling = self.params.coupling

        # The following terms are added in governing form testing.
        # They are not strictly part of the problem but need to be defined if not present!
        if not hasattr(self, 'body_force'):
            self.body_force = fenics.Constant(zeros(self.geometric_dimension))

        if not hasattr(self, 'rd_source_term'):
            self.rd_source_term = fenics.Constant(0)

        du = fenics.TrialFunction(self.functionspace.function_space)
        v0, v1 = fenics.TestFunctions(self.functionspace.function_space)
        self.solution = fenics.Function(self.functionspace.function_space)
        self.solution.label = 'solution_function'

        sol0, sol1 = fenics.split(self.solution)
        u_previous0, u_previous1 = fenics.split(u_previous)

        # Implement von Neuman Boundary Conditions
        #von_neuman_bc_terms = self._implement_von_neumann_bcs([v0, v1])
        #von_neuman_bc_term_mech, von_neuman_bc_term_rd = von_neuman_bc_terms

        # subspace 0 -> displacements
        # subspace 1 -> concentration

        dx_CSF = dx(self.subdomains.get_subdomain_id('CSF'))
        dx_WM = dx(self.subdomains.get_subdomain_id('WM'))
        dx_GM = dx(self.subdomains.get_subdomain_id('GM'))
        dx_Ventricles = dx(self.subdomains.get_subdomain_id('Ventricles'))

        dt = fenics.Constant(float(self.params.sim_time_step))
        dim = self.solution.geometric_dimension()

        if self.subdomains.get_subdomain_id('outside') is not None:
            dx_outside = dx(self.subdomains.get_subdomain_id('outside'))
            F_m_outside =   fenics.inner(mle.compute_stress(sol0, mu_OUT, lmbda_OUT), mle.compute_strain(v0)) * dx_outside \
                          - fenics.inner(mle.compute_stress(v0, mu_OUT, lmbda_OUT),mle.compute_growth_induced_strain(sol1, coupling, dim)) * dx_outside
            F_rd_outside =   dt * fenics.Constant(0) * fenics.inner(fenics.grad(sol1), fenics.grad(v1)) * dx_outside \
                           - dt * fenics.Constant(0) * v1 * dx_outside
        else:
            F_m_outside = 0
            F_rd_outside = 0

        F_m = fenics.inner(mle.compute_stress(sol0, mu_CSF, lmbda_CSF), mle.compute_strain(v0)) * dx_CSF \
              - fenics.inner(mle.compute_stress(v0, mu_CSF, lmbda_CSF), mle.compute_growth_induced_strain(sol1, coupling, dim)) * dx_CSF \
              + fenics.inner(mle.compute_stress(sol0, mu_WM, lmbda_WM), mle.compute_strain(v0)) * dx_WM \
              - fenics.inner(mle.compute_stress(v0, mu_WM, lmbda_WM), mle.compute_growth_induced_strain(sol1, coupling, dim)) * dx_WM \
              + fenics.inner(mle.compute_stress(sol0, mu_GM, lmbda_GM), mle.compute_strain(v0)) * dx_GM \
              - fenics.inner(mle.compute_stress(v0, mu_GM, lmbda_GM), mle.compute_growth_induced_strain(sol1, coupling, dim)) * dx_GM \
              + fenics.inner(mle.compute_stress(sol0, mu_VENT, lmbda_VENT), mle.compute_strain(v0)) * dx_Ventricles \
              - fenics.inner(mle.compute_stress(v0, mu_VENT, lmbda_VENT), mle.compute_growth_induced_strain(sol1, coupling, dim)) * dx_Ventricles \
              + F_m_outside
        # NOTE: No Von Neumann BC implemented here!

        F_rd = sol1 * v1 * dx \
               + dt * fenics.Constant(0) * fenics.inner(fenics.grad(sol1), fenics.grad(v1)) * dx_CSF \
               + dt * self.params.D_WM * fenics.inner(fenics.grad(sol1), fenics.grad(v1)) * dx_WM \
               + dt * self.params.D_GM * fenics.inner(fenics.grad(sol1), fenics.grad(v1)) * dx_GM \
               + dt * fenics.Constant(0) * fenics.inner(fenics.grad(sol1), fenics.grad(v1)) * dx_Ventricles \
               - u_previous1 * v1 * dx \
               - dt * fenics.Constant(0) * v1 * dx_CSF \
               - dt * mrd.compute_growth_logistic(sol1, self.params.rho_WM, 1.0) * v1 * dx_WM \
               - dt * mrd.compute_growth_logistic(sol1, self.params.rho_GM, 1.0) * v1 * dx_GM \
               - dt * fenics.Constant(0) * v1 * dx_Ventricles \
               - dt * self.rd_source_term * v1 * dx \
               + F_rd_outside
        # NOTE: No Von Neumann BC implemented here!

        F = F_m + F_rd

        J = fenics.derivative(F, self.solution, du)

        problem = fenics.NonlinearVariationalProblem(
            F, self.solution, bcs=self.bcs.dirichlet_bcs, J=J)
        solver = fenics.NonlinearVariationalSolver(problem)
        prm = solver.parameters
        prm['nonlinear_solver'] = 'snes'
        prm['snes_solver']['linear_solver'] = "lu"
        prm['snes_solver']['report'] = True
        prm['snes_solver']['error_on_nonconvergence'] = True
        prm['snes_solver']['preconditioner'] = 'amg'
        # prm.snes_solver.linear_solver = "lu"
        # prm.snes_solver.maximum_iterations = 20
        # prm.snes_solver.report = True
        # prm.snes_solver.error_on_nonconvergence = False
        # prm.snes_solver.preconditioner = 'amg'
        # prm = solver.parameters.newton_solver  # short form -> Newton Solver
        # prm.absolute_tolerance = 1E-11
        # prm.relative_tolerance = 1E-8
        # prm.maximum_iterations = 1000
        self.solver = solver
# ==============================================================================
# OPTIMISATION
# ==============================================================================

D = fenics.Constant(0.1)
rho = fenics.Constant(0.1)
c = fenics.Constant(0.2)

u = sim.run_for_adjoint([D, rho, c], output_dir=output_path)

disp, conc = fenics.split(u)

conc_opt = sim.functionspace.project_over_space(conc, subspace_id=1)
disp_opt = sim.functionspace.project_over_space(disp, subspace_id=0)

disp_sim_reloaded = fenics.Function(
    fenics.VectorFunctionSpace(mesh, "Lagrange", 1))
conc_sim_reloaded = fenics.Function(fenics.FunctionSpace(mesh, "Lagrange", 1))

# conc_sim = fenics.Function(sim.functionspace.get_functionspace(subspace_id=1))
# disp_sim = fenics.Function(sim.functionspace.get_functionspace(subspace_id=0))

with fenics.XDMFFile(path_to_xdmf) as infile:
    infile.read_checkpoint(disp_sim_reloaded, "disp")
    infile.read_checkpoint(conc_sim_reloaded, "conc")

#fenics.errornorm(disp_sim, disp_opt)
#fenics.errornorm(conc_sim, conc_sim_target)

# plott.show_img_seg_f(function=conc_sim, show=True,
#                      path=os.path.join(output_path, 'conc_target_reloaded.png'),
#                      dpi=300)