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)
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)
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 = []