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
#== threshold functions
thresh_1 = 0.2


def thresh(f, thresh):
    smooth_f = 0.05
    f_thresh = 0.5 * (fenics.tanh((f - thresh) / smooth_f) + 1)
    return f_thresh


m_target, w_target = fenics.split(u_target)
m, w = fenics.split(u)

J = fenics.Functional(
    fenics.inner(m - m_target, m - m_target) *
    sim.subdomains.dx +  # displacements
    fenics.inner(
        thresh(w, thresh_1) -
        thresh(w_target, thresh_1),  # thresholded concentration
        thresh(w, thresh_1) - thresh(w_target, thresh_1)) * sim.subdomains.dx)

controls = [fenics.ConstantControl(param) for param in params_init]


def eval_cb(j, a):
    params = [param.values() for param in a]
    print(j, *params)


reduced_functional = fenics.ReducedFunctional(J,
# ==============================================================================
# OPTIMISATION
# ==============================================================================
output_path = os.path.join(
    test_config.output_path,
    'test_case_simulation_tumor_growth_2D_subdomains_adjoint', 'adjoint')
fu.ensure_dir_exists(output_path)

D = fenics.Constant(0.1)
rho = fenics.Constant(0.01)
coupling = fenics.Constant(0.1)

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

J = fenics.Functional(
    fenics.inner(u - u_target, u - u_target) * sim.subdomains.dx)
controls = [
    fenics.ConstantControl(D),
    fenics.ConstantControl(rho),
    fenics.ConstantControl(coupling)
]


def eval_cb(j, a):
    D, rho, coupling = a
    print(j, D.values(), rho.values(), coupling.values())


reduced_functional = fenics.ReducedFunctional(J,
                                              controls,
                                              eval_cb_post=eval_cb)
Esempio n. 4
0
                                                annotate=False)
w_target = sim.functionspace.project_over_space(w_target_tmp,
                                                subspace_id=1,
                                                annotate=False)
# this level of noise still results in good approximation of original parameters
# conc_target_noise = add_noise(w_target, 0.01)
# disp_target_noise = add_noise(m_target, 0.005)
# conc_target_noise = add_noise(w_target, 0.02)
# disp_target_noise = add_noise(m_target, 0.01)
conc_target_noise = add_noise(w_target, 0.1)
disp_target_noise = add_noise(m_target, 0.05)

disp, conc = fenics.split(u)
alpha = 0.5
J = fenics.Functional(
    fenics.inner(conc - conc_target_noise, conc - conc_target_noise) *
    sim.subdomains.dx +
    fenics.inner(disp - disp_target_noise, disp - disp_target_noise) *
    sim.subdomains.dx + alpha * fenics.inner(u, u) * sim.subdomains.dx)

# 2) Noise
m_target_tmp, w_target_tmp = fenics.split(u_target)
m_target = sim.functionspace.project_over_space(m_target_tmp,
                                                subspace_id=0,
                                                annotate=False)
w_target = sim.functionspace.project_over_space(w_target_tmp,
                                                subspace_id=1,
                                                annotate=False)
# this level of noise still results in good approximation of original parameters
# conc_target_noise = add_noise(w_target, 0.01)
# disp_target_noise = add_noise(m_target, 0.005)
Esempio n. 5
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
#                      path=os.path.join(output_path, 'disp_target_reloaded.png'),
#                      dpi=300)
#
#
# plott.show_img_seg_f(function=sim.functionspace.project_over_space(conc_sim - conc_sim_target, subspace_id=1), show=True,
#                      path=os.path.join(output_path, 'conc_diff.png'),
#                      dpi=300)
# plott.show_img_seg_f(function=sim.functionspace.project_over_space(disp_sim - disp_sim_target, subspace_id=0), show=True,
#                      path=os.path.join(output_path, 'disp_diff.png'),
#                      dpi=300)

# J = fenics.Functional(   fenics.inner(conc_opt - conc_sim_target, conc_opt - conc_sim_target) * sim.subdomains.dx
#                        + fenics.inner(disp_opt - disp_sim_target, disp_opt - disp_sim_target) * sim.subdomains.dx)

J = fenics.Functional(
    fenics.inner(conc_opt - conc_sim_reloaded, conc_opt - conc_sim_reloaded) *
    sim.subdomains.dx +
    fenics.inner(disp_opt - disp_sim_reloaded, disp_opt - disp_sim_reloaded) *
    sim.subdomains.dx)

controls = [
    fenics.ConstantControl(D),
    fenics.ConstantControl(rho),
    fenics.ConstantControl(c)
]

import pandas as pd

opt_param_progress_post = []
opt_dj_progress_post = []