def setUp(self): self.nx = 40 self.ny = 20 mesh = fenics.RectangleMesh(fenics.Point(-2, -2), fenics.Point(2, 2), self.nx, self.ny) # function spaces U = fenics.VectorFunctionSpace(mesh, "Lagrange", 1) V = fenics.FunctionSpace(mesh, "Lagrange", 1) u_0_conc_expr = fenics.Expression('sqrt(pow(x[0]-x0,2)+pow(x[1]-y0,2)) < 1 ? (1.0) : (0.0)', degree=1, x0=1, y0=1) u_0_disp_expr = fenics.Constant((1.0, 1.0)) self.conc = fenics.project(u_0_conc_expr, V) self.disp = fenics.project(u_0_disp_expr, U) # 3D mesh3d = fenics.BoxMesh(fenics.Point(-2, -2, -2), fenics.Point(2, 2, 2), 10, 20, 30) # function spaces U3 = fenics.VectorFunctionSpace(mesh3d, "Lagrange", 1) V3 = fenics.FunctionSpace(mesh3d, "Lagrange", 1) u_0_conc_expr = fenics.Expression('sqrt(pow(x[0]-x0,2)+pow(x[1]-y0,2)+pow(x[2]-z0,2)) < 1 ? (1.0) : (0.0)', degree=1, x0=1, y0=1, z0=1 ) u_0_disp_expr = fenics.Constant((1.0, 1.0, 1.0)) self.conc3 = fenics.project(u_0_conc_expr, V3) self.disp3 = fenics.project(u_0_disp_expr, U3) self.test_path = os.path.join(config.output_dir_testing, 'test_data_io') fu.ensure_dir_exists(self.test_path)
def setUp(self): # Domain nx = ny = nz = 10 mesh = fenics.RectangleMesh(fenics.Point(-2, -2), fenics.Point(2, 2), nx, ny) # function spaces displacement_element = fenics.VectorElement("Lagrange", mesh.ufl_cell(), 1) concentration_element = fenics.FiniteElement("Lagrange", mesh.ufl_cell(), 1) element = fenics.MixedElement( [displacement_element, concentration_element]) subspace_names = {0: 'displacement', 1: 'concentration'} functionspace = FunctionSpace(mesh) functionspace.init_function_space(element, subspace_names) # build a 'solution' function u_0_conc_expr = fenics.Expression( 'sqrt(pow(x[0]-x0,2)+pow(x[1]-y0,2)) < 0.1 ? (1.0) : (0.0)', degree=1, x0=0.25, y0=0.5) u_0_disp_expr = fenics.Constant((0.0, 0.0)) self.U = functionspace.project_over_space(function_expr={ 0: u_0_disp_expr, 1: u_0_conc_expr }) self.tsd = TimeSeriesData(functionspace=functionspace, name='solution')
def test_implement_von_neumann_bcs(self): # seutp bcs self.bcs.setup_von_neumann_boundary_conditions(self.von_neuman_bcs) #v0, v1 = fenics.TestFunctions(self.functionspace.function_space) #param = self.subdomains.create_discontinuous_scalar_from_parameter_map(self.parameter, 'param') #bc_terms_0 = self.bcs.implement_von_neumann_bc(param * v0, subspace_id=0) #bc_terms_1 = self.bcs.implement_von_neumann_bc(param * v1, subspace_id=1) param = fenics.Constant(1.0) # compute surface integral based on implementation functions bc_boundary_auto_form = self.bcs.implement_von_neumann_bc(param * self.conc, subspace_id=1) bc_boundary_auto = fenics.assemble(bc_boundary_auto_form) # compute surface integral by defining form manually boundary_pos_id = self.subdomains.named_boundaries_id_dict['boundary_pos'] boundary_neg_id = self.subdomains.named_boundaries_id_dict['boundary_neg'] bc_boundary_pos_form = param * self.conc * fenics.Constant(1.0) * self.subdomains.dsn(boundary_pos_id) bc_boundary_neg_form = param * self.conc * fenics.Constant(-5.0) * self.subdomains.dsn(boundary_neg_id) bc_boundary = fenics.assemble(bc_boundary_pos_form) + fenics.assemble(bc_boundary_neg_form) self.assertAlmostEqual(bc_boundary_auto, bc_boundary)
def test_set_initial_value_expressions(self): u_0_conc_expr = fenics.Expression( 'sqrt(pow(x[0]-x0,2)+pow(x[1]-y0,2)) < 0.1 ? (1.0) : (0.0)', degree=1, x0=0.25, y0=0.5) u_0_disp_expr = fenics.Constant((0.0, 0.0)) ivs = {1: u_0_conc_expr, 0: u_0_disp_expr} self.params.set_initial_value_expressions(ivs) self.assertEqual(self.params.get_iv(1), u_0_conc_expr) self.assertEqual(self.params.get_iv(0), u_0_disp_expr)
def test_create_initial_value_function(self): self.params = Parameters(self.functionspace, self.subdomains, time_dependent=False) u_0_conc_expr = fenics.Expression( 'sqrt(pow(x[0]-x0,2)+pow(x[1]-y0,2)) < 0.1 ? (1.0) : (0.0)', degree=1, x0=0.25, y0=0.5) u_0_disp_expr = fenics.Constant((0.0, 0.0)) ivs = {1: u_0_conc_expr, 0: u_0_disp_expr} self.params.set_initial_value_expressions(ivs) u = self.params.create_initial_value_function()
def test_split_function(self): subspace_names = {0: 'displacement', 1: 'concentration'} functionspace = FunctionSpace(self.mesh) functionspace.init_function_space(self.element, subspace_names) u_0_conc_expr = fenics.Expression('sqrt(pow(x[0]-x0,2)+pow(x[1]-y0,2)) < 0.1 ? (1.0) : (0.0)', degree=1, x0=0.25, y0=0.5) u_0_disp_expr = fenics.Constant((0.0, 0.0)) U_orig = functionspace.project_over_space(function_expr={0: u_0_disp_expr, 1: u_0_conc_expr}) U = functionspace.split_function(U_orig) self.assertEqual(U_orig, U) U_1 = functionspace.split_function(U_orig, subspace_id=1) U_0 = functionspace.split_function(U_orig, subspace_id=0)
def setUp(self): # Domain nx = ny = nz = 10 self.mesh = fenics.RectangleMesh(fenics.Point(-2, -2), fenics.Point(2, 2), nx, ny) self.sim = TumorGrowth(self.mesh) label_funspace = fenics.FunctionSpace(self.mesh, "DG", 1) label_expr = fenics.Expression('(x[0]>=0.5) ? (1.0) : (2.0)', degree=1) self.labels = fenics.project(label_expr, label_funspace) self.tissue_map = {0: 'outside', 1: 'tissue', 2: 'tumor'} boundary = Boundary() self.boundary_dict = {'boundary_1': boundary, 'boundary_2': boundary} self.dirichlet_bcs = { 'clamped_0': { 'bc_value': fenics.Constant((0.0, 0.0)), 'boundary': Boundary(), 'subspace_id': 0 }, 'clamped_1': { 'bc_value': fenics.Constant((0.0, 0.0)), 'boundary_id': 0, 'subspace_id': 0 }, 'clamped_2': { 'bc_value': fenics.Constant((0.0, 0.0)), 'boundary_name': 'boundary_1', 'subspace_id': 0 } } self.von_neuman_bcs = { 'no_flux': { 'bc_value': fenics.Constant(0.0), 'boundary_id': 0, 'subspace_id': 1 }, 'no_flux_2': { 'bc_value': fenics.Constant(0.0), 'boundary_name': 'boundary_1', 'subspace_id': 1 }, } self.u_0_conc_expr = fenics.Expression( 'sqrt(pow(x[0]-x0,2)+pow(x[1]-y0,2)) < 0.1 ? (1.0) : (0.0)', degree=1, x0=0.25, y0=0.5) self.u_0_disp_expr = fenics.Constant((0.0, 0.0)) self.youngmod = {'outside': 10E6, 'tissue': 1, 'tumor': 1000} self.poisson = {'outside': 0.4, 'tissue': 0.4, 'tumor': 0.49} self.diffusion = {'outside': 0.0, 'tissue': 1.0, 'tumor': 0.1} self.prolif = {'outside': 0.0, 'tissue': 0.1, 'tumor': 1.0} self.coupling = {'outside': 0.0, 'tissue': 0.0, 'tumor': 0.5}
# Mesh nx = ny = 50 mesh = fenics.RectangleMesh(fenics.Point(-5, -5), fenics.Point(5, 5), nx, ny) # LabelMap label_funspace = fenics.FunctionSpace(mesh, "DG", 1) label_expr = fenics.Expression('(x[0]>=0.0) ? (1.0) : (2.0)', degree=1) labels = fenics.project(label_expr, label_funspace) tissue_map = {0: 'outside', 1: 'A', 2: 'B'} # Boundaries & BCs boundary = Boundary() boundary_dict = {'boundary_all': boundary} dirichlet_bcs = { 'clamped_outside': { 'bc_value': fenics.Constant((0.0, 0.0)), 'named_boundary': 'boundary_all', 'subspace_id': 0 }, # Test to show that Dirichlet BCs can be applied to subdomain interfaces # 'clamped_A_B' : {'bc_value': fenics.Constant((0.0, 0.0)), # 'subdomain_boundary': 'A_B', # 'subspace_id': 0} } von_neuman_bcs = { # not necessary to impose zero flux at domain boundary # 'no_flux_boundary': {'bc_value': fenics.Constant(0.0), # 'named_boundary': 'boundary_all', # 'subspace_id': 1} } # Initial Values
# ============================================================================== class Boundary(fenics.SubDomain): def inside(self, x, on_boundary): return on_boundary nx = ny = nz = 50 mesh = fenics.RectangleMesh(fenics.Point(-5, -5), fenics.Point(5, 5), nx, ny) boundary = Boundary() boundary_dict = {'boundary_all': boundary} dirichlet_bcs = { 'clamped_0': { 'bc_value': fenics.Constant((0.0, 0.0)), 'named_boundary': 'boundary_all', 'subspace_id': 0 } } von_neuman_bcs = {} u_0_conc_expr = fenics.Expression( ('exp(-a*pow(x[0]-x0, 2) - a*pow(x[1]-y0, 2))'), degree=1, a=1, x0=0.0, y0=0.0) u_0_disp_expr = fenics.Expression(('0', '0'), degree=1) # ==============================================================================
def setUp(self): # Domain nx = ny = nz = 10 self.nx, self.ny = nx, ny self.mesh = fenics.RectangleMesh(fenics.Point(-2, -2), fenics.Point(2, 2), nx, ny) # function spaces self.displacement_element = fenics.VectorElement("Lagrange", self.mesh.ufl_cell(), 1) self.concentration_element = fenics.FiniteElement("Lagrange", self.mesh.ufl_cell(), 1) self.element = fenics.MixedElement([self.displacement_element, self.concentration_element]) subspace_names = {0: 'displacement', 1: 'concentration'} self.functionspace = FunctionSpace(self.mesh) self.functionspace.init_function_space(self.element, subspace_names) # define 'solution' with concentration=1 everywhere self.conc_expr = fenics.Constant(1.0) self.conc = self.functionspace.project_over_space(self.conc_expr, subspace_name='concentration') # subdomains label_funspace = fenics.FunctionSpace(self.mesh, "DG", 1) label_expr = fenics.Expression('(x[0]>=0) ? (1.0) : (2.0)', degree=1) labels = fenics.project(label_expr, label_funspace) self.labels = labels self.tissue_id_name_map = {0: 'outside', 1: 'tissue', 2: 'tumor'} self.parameter = {'outside': 0.0, 'tissue': 1.0, 'tumor': 0.1} self.boundary_pos = BoundaryPos() self.boundary_neg = BoundaryNeg() boundary_dict = {'boundary_pos': self.boundary_pos, 'boundary_neg': self.boundary_neg} self.boundary_dict = boundary_dict self.subdomains = SubDomains(self.mesh) self.subdomains.setup_subdomains(label_function=self.labels) self.subdomains.setup_boundaries(tissue_map=self.tissue_id_name_map, boundary_fct_dict=self.boundary_dict) self.subdomains.setup_measures() # BCs self.bcs = BoundaryConditions(self.functionspace, self.subdomains) self.dirichlet_bcs = {'clamped_0': {'bc_value': fenics.Constant((0.0, 0.0)), 'boundary': BoundaryPos(), 'subspace_id': 0}, 'clamped_1': {'bc_value': fenics.Constant((0.0, 0.0)), 'subdomain_boundary': 'tissue_tumor', 'subspace_id': 0}, 'clamped_pos': {'bc_value': fenics.Constant((0.0, 0.0)), 'named_boundary': 'boundary_pos', 'subspace_id': 0}, 'clamped_neg': {'bc_value': fenics.Constant((0.0, 0.0)), 'named_boundary': 'boundary_neg', 'subspace_id': 0} } self.von_neuman_bcs = { 'flux_boundary_pos': {'bc_value': fenics.Constant(1.0), 'named_boundary': 'boundary_pos', 'subspace_id': 1}, 'flux_boundary_neg': {'bc_value': fenics.Constant(-5.0), 'named_boundary': 'boundary_neg', 'subspace_id': 1} # 'no_flux_domain_boundary': {'bc_value': fenics.Constant(1.0), # 'subdomain_boundary': 'tissue_tumor', # 'subspace_id': 1}, }
# Mesh nx = ny = 50 mesh = fenics.RectangleMesh(fenics.Point(-5, -5), fenics.Point(5, 5), nx, ny) # LabelMap label_funspace = fenics.FunctionSpace(mesh, "DG", 1) label_expr = fenics.Expression('(x[0]>=0.0) ? (1.0) : (2.0)', degree=1) labels = fenics.project(label_expr, label_funspace) tissue_map = {0: 'outside', 1: 'A', 2: 'B'} # Boundaries & BCs boundary = Boundary() boundary_dict = {'boundary_all': boundary} dirichlet_bcs = { 'clamped_outside': { 'bc_value': fenics.Constant((0.0, 0.0)), 'named_boundary': 'boundary_all', 'subspace_id': 0 }, # Test to show that Dirichlet BCs can be applied to subdomain interfaces # 'clamped_A_B' : {'bc_value': fenics.Constant((0.0, 0.0)), # 'subdomain_boundary': 'A_B', # 'subspace_id': 0} } von_neuman_bcs = { # not necessary to impose zero flux at domain boundary # 'no_flux_boundary': {'bc_value': fenics.Constant(0.0), # 'named_boundary': 'boundary_all', # 'subspace_id': 1} } # Initial Values
class Boundary(fenics.SubDomain): def inside(self, x, on_boundary): return on_boundary tissue_id_name_map = { 0: 'outside', 1: 'CSF', 3: 'WM', 2: 'GM', 4: 'Ventricles'} # Boundaries & BCs boundary = Boundary() boundary_dict = {'boundary_all': boundary} dirichlet_bcs = {'clamped_0': {'bc_value': fenics.Constant((0.0, 0.0)), 'subdomain_boundary': 'outside_CSF', 'subspace_id': 0}, 'clamped_1': {'bc_value': fenics.Constant((0.0, 0.0)), 'subdomain_boundary': 'outside_WM', 'subspace_id': 0}, 'clamped_2': {'bc_value': fenics.Constant((0.0, 0.0)), 'subdomain_boundary': 'outside_GM', 'subspace_id': 0} } von_neuman_bcs = { 'no_flux_boundary': {'bc_value': fenics.Constant(0.0), 'named_boundary': 'boundary_all', 'subspace_id': 1} }
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
# Problem Settings # ============================================================================== class Boundary(fenics.SubDomain): def inside(self, x, on_boundary): return on_boundary # Mesh nx = ny = 50 mesh = fenics.RectangleMesh(fenics.Point(-5, -5), fenics.Point(5, 5), nx, ny) # Boundaries & BCs boundary = Boundary() boundary_dict = {'boundary_all': boundary} dirichlet_bcs = {'clamped_boundary': {'bc_value': fenics.Constant((0.0, 0.0)), 'named_boundary': 'boundary_all', 'subspace_id': 0} } # no flux boundary BC not necessary von_neuman_bcs = { # 'no_flux_through_boundary': {'bc_value': fenics.Constant(0.0), # 'named_boundary': 'boundary_all', # 'subspace_id': 1}, } # Initial Values # u_0_conc_expr = fenics.Expression('sqrt(pow(x[0]-x0,2)+pow(x[1]-y0,2)) < 0.1 ? (1.0) : (0.0)', # degree=1, x0=0.0, y0=0.0) u_0_conc_expr = fenics.Expression( ('exp(-a*pow(x[0]-x0, 2) - a*pow(x[1]-y0, 2))'), degree=1, a=1, x0=0.0, y0=0.0)
# ============================================================================== class Boundary(fenics.SubDomain): def inside(self, x, on_boundary): return on_boundary tissue_id_name_map = {1: 'CSF', 3: 'WM', 2: 'GM', 4: 'Ventricles'} # Boundaries & BCs boundary = Boundary() boundary_dict = {'boundary_all': boundary} dirichlet_bcs = { 'clamped_0': { 'bc_value': fenics.Constant((0.0, 0.0, 0.0)), 'boundary_name': 'boundary_all', 'subspace_id': 0 } } # Simulation() generates boundaries between subdomains, # we want to apply no-flux von Neuman BC between tissue and CSF boundaries_no_flux = ['WM_Ventricles', 'GM_Ventricles', 'CSF_WM', 'CSF_GM'] von_neuman_bcs = {} for boundary in boundaries_no_flux: bc_name = "no_flux_%s" % boundary bc_dict = { 'bc_value': fenics.Constant(0.0), 'boundary_name': boundary,
# ============================================================================== class Boundary(fenics.SubDomain): def inside(self, x, on_boundary): return on_boundary tissue_id_name_map = {1: 'CSF', 3: 'WM', 2: 'GM', 4: 'Ventricles'} boundary = Boundary() boundary_dict = {'boundary_all': boundary} dirichlet_bcs = { 'clamped_0': { 'bc_value': fenics.Constant((0.0, 0.0)), 'named_boundary': 'boundary_all', 'subspace_id': 0 } } von_neuman_bcs = {} von_neuman_bcs = {} # Initial Values u_0_conc_expr = fenics.Expression( 'exp(-a*pow(x[0]-x0, 2) - a*pow(x[1]-y0, 2))', degree=1, a=0.5, x0=148,
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
# ============================================================================== class Boundary(fenics.SubDomain): def inside(self, x, on_boundary): return on_boundary tissue_id_name_map = {1: 'CSF', 3: 'WM', 2: 'GM', 4: 'Ventricles'} # Boundaries & BCs boundary = Boundary() boundary_dict = {'boundary_all': boundary} dirichlet_bcs = { 'clamped_0': { 'bc_value': fenics.Constant((0.0, 0.0, 0.0)), 'boundary_name': 'boundary_all', 'subspace_id': 0 } } # Simulation() generates boundaries between subdomains, # we want to apply no-flux von Neuman BC between tissue and CSF boundaries_no_flux = ['WM_Ventricles', 'GM_Ventricles', 'CSF_WM', 'CSF_GM'] von_neuman_bcs = {} for boundary in boundaries_no_flux: bc_name = "no_flux_%s" % boundary bc_dict = { 'bc_value': fenics.Constant(0.0), 'boundary_name': boundary,