def __init__(self, V, parameters=None): # Set parameters self.parameters = self.default_parameters() if parameters is not None: self.parameters.update(parameters) # Set-up mass matrix for L^2 projection self.V = V self.u = df.TrialFunction(self.V) self.v = df.TestFunction(self.V) self.m = df.inner(self.u, self.v) * df.dx() self.M = df.assemble(self.m) self.b = df.Vector(V.mesh().mpi_comm(), V.dim()) solver_type = self.parameters["linear_solver_type"] assert(solver_type == "lu" or solver_type == "cg"), \ "Expecting 'linear_solver_type' to be 'lu' or 'cg'" if solver_type == "lu": df.debug("Setting up direct solver for projecter") # Customize LU solver (reuse everything) solver = df.LUSolver(self.M) solver.parameters["same_nonzero_pattern"] = True solver.parameters["reuse_factorization"] = True else: df.debug("Setting up iterative solver for projecter") # Customize Krylov solver (reuse everything) solver = df.KrylovSolver("cg", "ilu") solver.set_operator(self.M) solver.parameters["preconditioner"]["structure"] = "same" # solver.parameters["nonzero_initial_guess"] = True self.solver = solver
def assign_initial_conditions(self, function): function_space = function.function_space() markers = self.markers() u = TrialFunction(function_space) v = TestFunction(function_space) dy = Measure("dx", domain=self.mesh(), subdomain_data=markers) # Define projection into multiverse a = inner(u, v) * dy() Ls = list() for k, model in enumerate(self.models()): ic = model.initial_conditions() # Extract initial conditions n_k = model.num_states() # Extract number of local states i_k = self.keys()[k] # Extract domain index of cell model k L_k = sum(ic[j] * v[j] * dy(i_k) for j in range(n_k + 1)) # include v and s Ls.append(L_k) L = sum(Ls) # solve(a == L, function) # really inaccurate params = df.KrylovSolver.default_parameters() params["absolute_tolerance"] = 1e-14 params["relative_tolerance"] = 1e-14 params["nonzero_initial_guess"] = True solver = df.KrylovSolver() solver.update_parameters(params) A, b = df.assemble_system(a, L) solver.set_operator(A) solver.solve(function.vector(), b)
def set_solver(): # "hypre_amg") #"hypre_euclid") # "hypre_amg") # "petsc_amg" "petsc_amg" solver = d.KrylovSolver("cg", "hypre_amg") solver.parameters["maximum_iterations"] = 1000 solver.parameters["absolute_tolerance"] = 1E-8 solver.parameters["error_on_nonconvergence"] = True solver.parameters["monitor_convergence"] = True # solver.parameters["divergence_limit"] = 1E+6 # solver.parameters["nonzero_initial_guess"] = True d.info(solver.parameters, verbose=True) d.set_log_level(d.PROGRESS) return solver
def solve(AA, uu, bb, *, krylov_args=('cg', 'hypre_amg'), direct_args=('mumps', )): try: solver = dolfin.KrylovSolver(*krylov_args) it = solver.solve(AA, uu.vector(), bb) print(f'krylov iterations: {it}') except: dolfin.solve(AA, uu.vector(), bb, *direct_args) print(f'direct solve after krylov failure') it = -1 return it
def __init__(self,mesh,m, parameters=sb.default_parameters , degree=1, element="CG", project_method='magpar', unit_length=1,Ms = 1.0,bench = False, mac=0.3,p=3,num_limit=100): sb.FemBemDeMagSolver.__init__(self,mesh,m, parameters, degree, element=element, project_method = project_method, unit_length = unit_length,Ms = Ms,bench = bench) self.__name__ = "Treecode Demag Solver" #Linear Solver parameters method = parameters["poisson_solver"]["method"] pc = parameters["poisson_solver"]["preconditioner"] self.poisson_solver = df.KrylovSolver(self.poisson_matrix, method, pc) self.phi1 = df.Function(self.V) self.phi2 = df.Function(self.V) # Eq (1) and code-block 2 - two first lines. b = self.Ms*df.inner(self.w, df.grad(self.v))*df.dx self.D = df.assemble(b) self.p=p self.mac=mac self.num_limit=num_limit self.mesh=mesh self.bmesh = df.BoundaryMesh(mesh,False) self.b2g_map = self.bmesh.vertex_map().array() self.compute_triangle_normal() self.__compute_bsa() fast_sum=FastSum(p=self.p,mac=self.mac,num_limit=self.num_limit) coords=self.bmesh.coordinates() face_nodes=np.array(self.bmesh.cells(),dtype=np.int32) fast_sum.init_mesh(coords,self.t_normals,face_nodes,self.vert_bsa) self.fast_sum=fast_sum self.phi2_b = np.zeros(self.bmesh.num_vertices())
def assign_ic_subdomain( *, brain: CoupledBrainModel, vs_prev: df.Function, value: float, subdomain_id: int, subfunction_index: int ) -> None: """ Compute a function with `value` in the subdomain corresponding to `subdomain_id`. Assign this function to subfunction `subfunction_index` of vs_prev. """ mesh = brain._mesh cell_function = brain._cell_function dX = df.Measure("dx", domain=mesh, subdomain_data=cell_function) V = df.FunctionSpace(mesh, "DG", 0) u = df.TrialFunction(V) v = df.TestFunction(V) sol = df.Function(V) sol.vector().zero() # Make sure it is initialised to zero F = -u*v*dX(subdomain_id) + df.Constant(value)*v*dX(subdomain_id) a = df.lhs(F) L = df.rhs(F) A = df.assemble(a, keep_diagonal=True) A.ident_zeros() b = df.assemble(L) solver = df.KrylovSolver("cg", "petsc_amg") solver.set_operator(A) solver.solve(sol.vector(), b) VCG = df.FunctionSpace(mesh, "CG", 1) v_new = df.Function(VCG) v_new.interpolate(sol) Vp = vs_prev.function_space().sub(subfunction_index) merger = df.FunctionAssigner(Vp, VCG) merger.assign(vs_prev.sub(subfunction_index), v_new)
def solve_IC(mesh: df.Mesh, cell_function: df.MeshFunction, tag_ic_dict: tp.Dict[int, tp.List[float]], dimension: int) -> df.Function: """Solve a Poisson equation in order to assign values from a cell function to a (CG1) function NB! This is not precise --- Nah, it is fairly ok with the interpolation """ dX = df.Measure("dx", domain=mesh, subdomain_data=cell_function) DG_fs = df.VectorFunctionSpace(mesh, "DG", 0, dim=dimension) u = df.TrialFunction(DG_fs) v = df.TestFunction(DG_fs) sol = df.Function(DG_fs) sol.vector().zero() # Make sure it is initialised to zero # NB! For some reason map(int, cell_tags) does not work with the cell function. F = 0 for ct, ic in tag_ic_dict.items(): F += -df.dot(u, v) * dX(ct) + df.dot(df.Constant(tuple(ic)), v) * dX(ct) a = df.lhs(F) L = df.rhs(F) # TODO: Why keep diagonal and ident_zeros? A = df.assemble(a, keep_diagonal=True) A.ident_zeros() b = df.assemble(L) solver = df.KrylovSolver("cg", "petsc_amg") solver.set_operator(A) solver.solve(sol.vector(), b) # clamp to int # sol.vector()[:] = sol.vector().get_local() target_fs = df.VectorFunctionSpace(mesh, "CG", 1, dim=dimension) solsol = df.Function(target_fs) solsol.interpolate(sol) return solsol
def set_solver(self, solver_method="mumps", **kwargs): """ Choose the type of the solver and its method. An up-to-date list of the available solvers and preconditioners can be obtained with dolfin.list_linear_solver_methods() and dolfin.list_krylov_solver_preconditioners(). kwargs: type e.g. 'LU', preconditioner e.g. 'default' """ s_type = kwargs.pop("type", None) s_precond = kwargs.pop("preconditioner", "default") if s_type is None: if solver_method in DOLFIN_KRYLOV_METHODS.keys(): s_type = "Krylov" elif solver_method in DOLFIN_LU_METHODS.keys(): s_type = "LU" else: raise RuntimeError("The indicated solver method is unknown.") else: if not (solver_method in DOLFIN_KRYLOV_METHODS.keys() or solver_method in DOLFIN_LU_METHODS.keys()): raise RuntimeError("The indicated solver method is unknown.") self._solver = dict(type=s_type, method=solver_method, preconditioner=s_precond) if s_precond: self._solver["preconditioner"] = s_precond if s_type == "Krylov": self.solver = fe.KrylovSolver(self.K, solver_method) elif s_type == "LU": self.solver = fe.LUSolver(self.K, solver_method) if s_precond != "default": self.solver.parameters.preconditioner = s_precond return self.solver
def solve_tr_dir__const_rheo(mesh_name, hol_cyl, deg_choice, T_in_expr, T_inf_expr, HTC, T_old_v, k_mesh, cp_mesh, rho_mesh, k_mesh_old, cp_mesh_old, rho_mesh_old, dt, time_v, theta, bool_plot, bool_solv, savings_do, logger_f): ''' mesh_name: a proper XML file. bool_plot: plots if bool_plot = 1. Solves a direct, steady-state heat conduction problem, and returns A_np, b_np, D_np, T_np, bool_ex, bool_in. A_np: stiffness matrix, ordered by vertices. b_np: integrated volumetric heat sources and surface heat fluxes, ordered by vertices. The surface heat fluxes come from the solution to the direct problem; hence, these terms will not be there in a real IHCP. D_np: integrated Laplacian of T, ordered by vertices. Option 2. The Laplacian of q is properly assembled from D_np. If do.dx(domain = hol_cyl) -> do.Measure('ds')[boundary_faces] and do.Measure('ds')[boundary_faces] -> something representative of Gamma, I would get option 1. T_np: solution to the direct heat conduction problem, ordered by vertices. bool_ex: boolean array declaring which vertices lie on the outer boundary. bool_in: boolean array indicating which vertices lie on the inner boundary. T_sol: solution to the direct heat conduction problem. deg_choice: degree in FunctionSpace. hol_cyl: mesh. ''' #comm1 = MPI.COMM_WORLD #current proc #rank1 = comm1.Get_rank() V = do.FunctionSpace(hol_cyl, 'CG', deg_choice) if 'hollow' in mesh_name and 'cyl' in mesh_name: from hollow_cyl_inv_mesh import geo_fun as geo_fun_hollow_cyl geo_params_d = geo_fun_hollow_cyl()[1] #x_c is a scalar here #y_c is a scalar here elif 'four' in mesh_name and 'cyl' in mesh_name: from four_hole_cyl_inv_mesh import geo_fun as geo_fun_four_hole_cyl geo_params_d = geo_fun_four_hole_cyl()[1] #x_c is an array here #y_c is an array here x_c_l = [geo_params_d['x_0_{}'.format(itera)] for itera in xrange(4)] y_c_l = [geo_params_d['y_0_{}'.format(itera)] for itera in xrange(4)] elif 'one_hole_cir' in mesh_name: from one_hole_cir_adj_mesh import geo_fun as geo_fun_one_hole_cir geo_params_d = geo_fun_one_hole_cir()[1] #x_c is an array here #y_c is an array here x_c_l = [geo_params_d['x_0']] y_c_l = [geo_params_d['y_0']] elif 'reinh_cir' in mesh_name: from reinh_cir_adj_mesh import geo_fun as geo_fun_one_hole_cir geo_params_d = geo_fun_one_hole_cir()[1] #x_c is an array here #y_c is an array here x_c_l = [geo_params_d['x_0']] y_c_l = [geo_params_d['y_0']] elif 'small_circle' in mesh_name: from four_hole_small_cir_adj_mesh import geo_fun as geo_fun_four_hole_cir geo_params_d = geo_fun_four_hole_cir()[1] #x_c is an array here #y_c is an array here x_c_l = [geo_params_d['x_0_{}'.format(itera)] for itera in xrange(4)] y_c_l = [geo_params_d['y_0_{}'.format(itera)] for itera in xrange(4)] #center of the cylinder base x_c = geo_params_d['x_0'] y_c = geo_params_d['y_0'] R_in = geo_params_d['R_in'] R_ex = geo_params_d['R_ex'] #define variational problem T = do.TrialFunction(V) g = do.Function(V) v = do.TestFunction(V) T_old = do.Function(V) T_inf = do.Function(V) #scalar T_old.vector()[:] = T_old_v T_inf.vector()[:] = T_inf_expr #solution T_sol = do.Function(V) #scalar T_sol.vector()[:] = T_old_v # Create boundary markers mark_all = 3 mark_in = 4 mark_ex = 5 #x_c is an array here #y_c is an array here g_in = g_in_mesh(mesh_name, x_c_l, y_c_l, R_in) g_ex = g_ex_mesh(mesh_name, x_c, y_c, R_ex) in_boundary = do.AutoSubDomain(g_in) ex_boundary = do.AutoSubDomain(g_ex) #normal unitNormal = do.FacetNormal(hol_cyl) boundary_faces = do.MeshFunction('size_t', hol_cyl, hol_cyl.topology().dim() - 1) boundary_faces.set_all(mark_all) in_boundary.mark(boundary_faces, mark_in) ex_boundary.mark(boundary_faces, mark_ex) bc_in = do.DirichletBC(V, T_in_expr, boundary_faces, mark_in) #bc_ex = do.DirichletBC(V, T_ex_expr, boundary_faces, mark_ex) bcs = [bc_in] #k = do.Function(V) #W/m/K #k.vector()[:] = k_mesh #A0 = k * do.dot(do.grad(T), do.grad(v)) * do.dx(domain = hol_cyl) A = dt / 2. * k_mesh * do.dot(do.grad(T), do.grad(v)) * do.dx(domain = hol_cyl) + \ rho_mesh * cp_mesh * T * v * do.dx(domain = hol_cyl) A_full = A + dt / 2. * HTC * T * v * do.ds( mark_ex, domain=hol_cyl, subdomain_data=boundary_faces) L = -dt / 2. * k_mesh_old * do.dot(do.grad(T_old), do.grad(v)) * \ do.dx(domain = hol_cyl) + \ rho_mesh_old * cp_mesh_old * T_old * v * do.dx(domain = hol_cyl) - \ dt / 2. * HTC * (T_old) * v * do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) + \ dt * HTC * T_inf * v * do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) #numpy version of A, T, and (L + int_fluxT) #A_np__not_v2d = do.assemble(A).array() #before applying BCs - needs v2d #L_np__not_v2d = do.assemble(L).array() #before applying BCs - needs v2d #Laplacian of T, without any -1/k int_S q*n*v dS ''' Approximated integral of the Laplacian of T. Option 2. The Laplacian of q is properly assembled from D_np. If do.dx(domain = hol_cyl) -> do.Measure('ds')[boundary_faces] and do.Measure('ds')[boundary_faces] -> something representative of Gamma, I would get option 1. ''' #D_np__not_v2d = do.assemble(-do.dot(do.grad(T), do.grad(v)) * do.dx(domain = hol_cyl) + # do.dot(unitNormal, do.grad(T)) * v * # do.Measure('ds')[boundary_faces]).array() #print np.max(D_np__not_v2d)#, np.max(A_np__not_v2d) #logger_f.warning('shape of D_np = {}, {}'.format(D_np__not_v2d.shape[0], #D_np__not_v2d.shape[1])) #nonzero_entries = [] #for row in D_np__not_v2d: # nonzero_entries += [len(np.where(abs(row) > 1e-16)[0])] #logger_f.warning('max, min, and mean of nonzero_entries = {}, {}, {}'.format( # max(nonzero_entries), min(nonzero_entries), np.mean(nonzero_entries))) #solver parameters #linear solvers from #list_linear_solver_methods() #preconditioners from #do.list_krylov_solver_preconditioners() solver = do.KrylovSolver('gmres', 'ilu') do.info(solver.parameters, True) #prints default values solver.parameters['relative_tolerance'] = 1e-16 solver.parameters['maximum_iterations'] = 20000000 solver.parameters['monitor_convergence'] = True #on the screen #http://fenicsproject.org/qa/1124/is-there-a-way-to-set-the-inital-guess-in-the-krylov-solver '''solver.parameters['nonzero_initial_guess'] = True''' solver.parameters['absolute_tolerance'] = 1e-15 #uses whatever in q_v as my initial condition #the next lines are used for CHECK 3 only #A_sys, b_sys = do.assemble_system(A, L, bcs) do.File( os.path.join(savings_do, '{}__markers.pvd'.format( mesh_name.split('.')[0]))) << boundary_faces if bool_plot: do.plot(boundary_faces, '3D mesh', title='boundary markers') #storage T_sol_d = {} g_d = {} if bool_solv == 1: xdmf_DHCP_T = do.File(os.path.join(savings_do, 'DHCP', 'T.pvd')) xdmf_DHCP_q = do.File(os.path.join(savings_do, 'DHCP', 'q.pvd')) for count_t_i, t_i in enumerate(time_v[1:]): #T_in_expr.ts = t_i #T_ex_expr.ts = t_i #storage T_sol_d[count_t_i] = do.Function(V) T_sol_d[count_t_i].vector()[:] = T_sol.vector().array() do.solve(A_full == L, T_sol, bcs) ''' TO BE UPDATED: rheology is not updated ''' #updates L T_old.assign(T_sol) T_sol.rename('DHCP_T', 'temperature from DHCP') #write solution to file #paraview format xdmf_DHCP_T << (T_sol, t_i) #plot solution if bool_plot: do.plot(T_sol, title='T') #, interactive = True) logger_f.warning('len(T) = {}'.format(len(T_sol.vector().array()))) print 'T: count_t = {}, min(T_DHCP) = {}'.format( count_t_i, min(T_sol_d[count_t_i].vector().array())) print 'T: count_t = {}, max(T_DHCP) = {}'.format( count_t_i, max(T_sol_d[count_t_i].vector().array())), '\n' #save flux - required for solving IHCP #same result if do.ds(mark_ex, subdomain_data = boundary_faces) #instead of do.Measure('ds')[boundary_faces] #Langtangen, p. 37: #either do.dot(do.nabla_grad(T), unitNormal) #or do.dot(unitNormal, do.grad(T)) #int_fluxT = do.assemble(-k * do.dot(unitNormal, do.grad(T_sol)) * v * # do.Measure('ds')[boundary_faces]) fluxT = do.project( -k_mesh * do.grad(T_sol), do.VectorFunctionSpace(hol_cyl, 'CG', deg_choice, dim=2)) if bool_plot: do.plot(fluxT, title='flux at iteration = {}'.format(count_t_i)) fluxT.rename('DHCP_flux', 'flux from DHCP') xdmf_DHCP_q << (fluxT, t_i) print 'DHCP: iteration = {}'.format(count_t_i) #################################################### #full solution #T_sol_full = do.Vector() #T_sol.vector().gather(T_sol_full, np.array(range(V.dim()), 'intc')) #################################################### count_t_i += 1 #copy previous lines #storage T_sol_d[count_t_i] = do.Function(V) T_sol_d[count_t_i].vector()[:] = T_sol.vector().array() for count_t_i, t_i in enumerate(time_v): #storage g_d[count_t_i] = do.Function(V) g_d[count_t_i].vector()[:] = g.vector().array() gdim = hol_cyl.geometry().dim() dofmap = V.dofmap() dofs = dofmap.dofs() #Get coordinates as len(dofs) x gdim array dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim)) #booleans corresponding to the outer boundary -> ints since they are sent to root = 0 bool_ex = 1. * np.array([g_ex(dof_x) for dof_x in dofs_x]) #booleans corresponding to the inner boundary -> ints since they are sent to root = 0 bool_in = 1. * np.array([g_in(dof_x) for dof_x in dofs_x]) T_np_ex = [] T_np_in = [] for i_coor, coor in enumerate(dofs_x): if g_ex(coor): T_np_ex += [T_sol.vector().array()[i_coor]] if g_in(coor): T_np_in += [T_sol.vector().array()[i_coor]] print 'CHECK: mean(T) on the outer boundary = ', np.mean(np.array(T_np_ex)) print 'CHECK: mean(T) on the inner boundary = ', np.mean(np.array(T_np_in)) print 'CHECK: mean(HTC) = ', np.mean(do.project(HTC, V).vector().array()) #v2d = do.vertex_to_dof_map(V) #orders by hol_cyl.coordinates() if deg_choice == 1: print 'len(dof_to_vertex_map) = ', len(do.dof_to_vertex_map(V)) print 'min(dofs) = ', min(dofs), ', max(dofs) = ', max(dofs) print 'len(bool ex) = ', len(bool_ex) print 'len(bool in) = ', len(bool_in) print 'bool ex[:10] = ', repr(bool_ex[:10]) print 'type(T) = ', type(T_sol.vector().array()) #first global results, then local results return A, L, g_d, \ V, v, k_mesh, \ mark_in, mark_ex, \ boundary_faces, bool_ex, \ R_in, R_ex, T_sol_d, deg_choice, hol_cyl, \ unitNormal, dofs_x
def nablau_fun( V, v, hol_cyl, A, boundary_faces, mark_in, dg_d, #S_in k_mesh_old, cp_mesh_old, rho_mesh_old, dt, time_v, theta, itera): ''' Sensitivity problem. Solves A u = L. A = dt * theta * k_mesh * do.dot(do.grad(T), do.grad(v)) * do.dx(domain = hol_cyl) + \ rho_mesh * cp_mesh * T * v * do.dx(domain = hol_cyl) Solved after setting dg_in = p^k. ''' #solver parameters #linear solvers from #list_linear_solver_methods() #preconditioners from #do.list_krylov_solver_preconditioners() solver = do.KrylovSolver('gmres', 'ilu') do.info(solver.parameters, False) #prints default values solver.parameters['relative_tolerance'] = 1e-13 solver.parameters['maximum_iterations'] = 200000 solver.parameters['monitor_convergence'] = True #on the screen #http://fenicsproject.org/qa/1124/ #is-there-a-way-to-set-the-inital-guess-in-the-krylov-solver '''solver.parameters['nonzero_initial_guess'] = True''' #solver.parameters['absolute_tolerance'] = 1e-15 #uses whatever in q_v as my initial condition #starts from 0 #u_stept = do.TrialFunction(V) u_step3 = do.Function(V) #starts from 0 u_old = do.Function(V) u_step3_d = {} theta = do.Constant(theta) dt = do.Constant(dt) #A = dt / 2. * k_mesh_old * do.dot(do.grad(u_stept), do.grad(v)) * do.dx(domain = hol_cyl) + \ # rho_mesh_old * cp_mesh_old * u_stept * v * do.dx(domain = hol_cyl) for count_t_i, t_i in enumerate(time_v[1:]): #storage u_step3_d[count_t_i] = do.Function(V) u_step3_d[count_t_i].vector()[:] = u_step3.vector().array() #int_fluxT_ex = 0 int_fluxT_in = dg_d[count_t_i + 1] * v * do.ds( mark_in, domain=hol_cyl, subdomain_data=boundary_faces) int_fluxT_in_old = dg_d[count_t_i] * v * do.ds( mark_in, domain=hol_cyl, subdomain_data=boundary_faces) #L -= (int_fluxT_in + int_fluxT_ex) L_old = -dt * (1. - theta) * k_mesh_old * do.dot(do.grad(u_old), do.grad(v)) * \ do.dx(domain = hol_cyl) + \ rho_mesh_old * cp_mesh_old * u_old * v * do.dx(domain = hol_cyl) L = L_old + (dt * theta * int_fluxT_in + dt * (1. - theta) * int_fluxT_in_old) do.solve(A == L, u_step3) print 'u: count_t = {}, min(dg) = {}'.format( count_t_i, min(dg_d[count_t_i].vector().array())) print 'u: count_t = {}, max(dg) = {}'.format( count_t_i, max(dg_d[count_t_i].vector().array())) print 'u: count_t = {}, min(int_fluxT_in) = {}'.format( count_t_i, min(do.assemble(int_fluxT_in).array())) print 'u: count_t = {}, max(int_fluxT_in) = {}'.format( count_t_i, max(do.assemble(int_fluxT_in).array())) print 'u: count_t = {}, min(L) = {}'.format( count_t_i, min(do.assemble(L).array())) print 'u: count_t = {}, max(L) = {}'.format( count_t_i, max(do.assemble(L).array())) print 'u: count_t = {}, min(u) = {}'.format( count_t_i, min(u_step3.vector().array())) print 'u: count_t = {}, max(u) = {}'.format( count_t_i, max(u_step3.vector().array())), '\n' u_old.assign(u_step3) count_t_i += 1 #storage u_step3_d[count_t_i] = do.Function(V) u_step3_d[count_t_i].vector()[:] = u_step3.vector().array() return u_step3_d
def nablap_fun( V, v, hol_cyl, A, boundary_faces, mark_ex, T_step_d, T_exp_d, #S_ex k_mesh_oldp, cp_mesh_oldp, rho_mesh_oldp, dt, time_v, theta, itera, mesh_name, savings_do): ''' Adjoint problem. Solves A p = L. A = dt * theta * k_mesh * do.dot(do.grad(p), do.grad(v)) * do.dx(domain = hol_cyl) + \ rho_mesh * cp_mesh * p * v * do.dx(domain = hol_cyl) T_stepp: from T_step flipped. T_exp : from T_ex flipped. ''' #solver parameters #linear solvers from #list_linear_solver_methods() #preconditioners from #do.list_krylov_solver_preconditioners() solver = do.KrylovSolver('gmres', 'ilu') do.info(solver.parameters, False) #prints default values solver.parameters['relative_tolerance'] = 1e-13 solver.parameters['maximum_iterations'] = 2000000 solver.parameters['monitor_convergence'] = True #on the screen #http://fenicsproject.org/qa/1124/ #is-there-a-way-to-set-the-inital-guess-in-the-krylov-solver '''solver.parameters['nonzero_initial_guess'] = True''' #solver.parameters['absolute_tolerance'] = 1e-15 #uses whatever in q_v as my initial condition #p_stept = do.TrialFunction(V) p_step2 = do.Function(V) #starts from 0 p_old = do.Function(V) p_step2_d = {} #e.g., e.g., count_t_i = 100 #storage p_step2_d[len(time_v) - 1] = do.Function(V) p_step2_d[len(time_v) - 1].vector()[:] = p_old.vector().array() theta = do.Constant(theta) dt = do.Constant(dt) p_step2_f = do.File(os.path.join(savings_do, str(itera), 'adj_IHCP.pvd')) #A = dt / 2. * k_mesh_oldp * do.dot(do.grad(p_stept), do.grad(v)) * do.dx(domain = hol_cyl) + \ # rho_mesh_oldp * cp_mesh_oldp * p_stept * v * do.dx(domain = hol_cyl) #runs backwards in time for count_t_i, t_i in reversed(list(enumerate(time_v[:-1]))): #int_fluxT_in = 0 #e.g., count_t_i = 99 int_fluxT_ex = (T_step_d[count_t_i] - T_exp_d[count_t_i]) * v * \ do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) #'old' = old tau = new time; e.g., count_t_i + 1 = 100 int_fluxT_ex_old = (T_step_d[count_t_i + 1] - T_exp_d[count_t_i + 1]) * v * \ do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) L_oldp = -dt * (1. - theta) * k_mesh_oldp * do.dot(do.grad(p_old), do.grad(v)) * \ do.dx(domain = hol_cyl) + \ rho_mesh_oldp * cp_mesh_oldp * p_old * v * do.dx(domain = hol_cyl) #before: #L = L_oldp - (dt * theta * int_fluxT_ex + dt * (1. - theta) * int_fluxT_ex_old) L = L_oldp + (dt * theta * int_fluxT_ex + dt * (1. - theta) * int_fluxT_ex_old) do.solve(A == L, p_step2) print 'p: count_t = {}, min(T_step_d) = {}'.format( count_t_i, min(T_step_d[count_t_i].vector().array())) print 'p: count_t = {}, max(T_step_d) = {}'.format( count_t_i, max(T_step_d[count_t_i].vector().array())) print 'p: count_t = {}, min(int_fluxT_ex) = {}'.format( count_t_i, min(do.assemble(int_fluxT_ex).array())) print 'p: count_t = {}, max(int_fluxT_ex) = {}'.format( count_t_i, max(do.assemble(int_fluxT_ex).array())) print 'p: count_t = {}, min(L) = {}'.format( count_t_i, min(do.assemble(L).array())) print 'p: count_t = {}, max(L) = {}'.format( count_t_i, max(do.assemble(L).array())) print 'p: count_t = {}, min(p) = {}'.format(count_t_i, min(p_step2.vector())) print 'p: count_t = {}, max(p) = {}'.format( count_t_i, max(p_step2.vector())), '\n' p_old.assign(p_step2) p_step2.rename('dual_T', 'dual temperature') #storage p_step2_d[count_t_i] = do.Function(V) p_step2_d[count_t_i].vector()[:] = p_step2.vector().array() p_step2_f << (p_step2, t_i) return p_step2_d
def nablaT_fun( V, v, hol_cyl, A, boundary_faces, mark_in, mark_ex, T_old_v, g_d, #S_in T_sol_d, T_ex, #S_ex unitNormal, k_mesh_old, cp_mesh_old, rho_mesh_old, dt, time_v, theta, itera, mesh_name, savings_do): ''' Direct problem. Solves A T = L. A = dt * theta * k_mesh * do.dot(do.grad(T), do.grad(v)) * do.dx(domain = hol_cyl) + \ rho_mesh * cp_mesh * T * v * do.dx(domain = hol_cyl) int_fluxT_ex = -k_mesh * do.dot(unitNormal, do.grad(T_sol)) * v * \ do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) no T_ex on outer boundary. ''' #solver parameters #linear solvers from #list_linear_solver_methods() #preconditioners from #do.list_krylov_solver_preconditioners() solver = do.KrylovSolver('gmres', 'ilu') do.info(solver.parameters, False) #prints default values solver.parameters['relative_tolerance'] = 1e-13 solver.parameters['maximum_iterations'] = 2000000 solver.parameters['monitor_convergence'] = True #on the screen #http://fenicsproject.org/qa/1124/ #is-there-a-way-to-set-the-inital-guess-in-the-krylov-solver solver.parameters['nonzero_initial_guess'] = True #solver.parameters['absolute_tolerance'] = 1e-15 #T_stept = do.TrialFunction(V) T_step1 = do.Function(V) T_old = do.Function(V) #T_old_v is a scalar T_step1.vector()[:] = T_old_v T_old.vector()[:] = T_old_v T_step1_d = {} print 'T: min(g_d[0]) = ', min(g_d[0].vector().array()) print 'T: max(g_d[0]) = ', max(g_d[0].vector().array()) theta = do.Constant(theta) dt = do.Constant(dt) T_step1_f = do.File(os.path.join(savings_do, str(itera), 'dir_IHCP.pvd')) #A = dt / 2. * k_mesh_old * do.dot(do.grad(T_stept), do.grad(v)) * do.dx(domain = hol_cyl) + \ # rho_mesh_old * cp_mesh_old * T_stept * v * do.dx(domain = hol_cyl) for count_t_i, t_i in enumerate(time_v[1:]): #storage T_step1_d[count_t_i] = do.Function(V) T_step1_d[count_t_i].vector()[:] = T_step1.vector().array() #g is a k * dot(grad(T), n) int_fluxT_in = g_d[count_t_i + 1] * v * do.ds( mark_in, domain=hol_cyl, subdomain_data=boundary_faces) int_fluxT_in_old = g_d[count_t_i] * v * do.ds( mark_in, domain=hol_cyl, subdomain_data=boundary_faces) int_fluxT_ex = + k_mesh_old * do.dot(unitNormal, do.grad(T_sol_d[count_t_i + 1])) * \ v * do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) int_fluxT_ex_old = + k_mesh_old * do.dot(unitNormal, do.grad(T_sol_d[count_t_i])) * \ v * do.ds(mark_ex, domain = hol_cyl, subdomain_data = boundary_faces) #print 'T: type(int_fluxT_in) = ', type(int_fluxT_in) #print 'T: type(int_fluxT_in_old) = ', type(int_fluxT_in_old) #print 'T: min(int_fluxT_in) = ', min(do.assemble(int_fluxT_in)) #L -= (int_fluxT_in + int_fluxT_ex) L_old = -dt * (1. - theta) * k_mesh_old * do.dot(do.grad(T_old), do.grad(v)) * \ do.dx(domain = hol_cyl) + \ rho_mesh_old * cp_mesh_old * T_old * v * do.dx(domain = hol_cyl) L = L_old + (dt * theta * int_fluxT_in + dt * (1. - theta) * int_fluxT_in_old + dt * theta * int_fluxT_ex + dt * (1. - theta) * int_fluxT_ex_old) do.solve(A == L, T_step1) #, bc_ex) print 'T: count_t = {}, avg(g) = {}'.format( count_t_i, np.mean(g_d[count_t_i + 1].vector().array())) print 'T: count_t = {}, min(L) = {}'.format( count_t_i, min(do.assemble(L).array())) print 'T: count_t = {}, max(L) = {}'.format( count_t_i, max(do.assemble(L).array())) print 'T: count_t = {}, min(T) = {}'.format( count_t_i, min(T_step1.vector().array())) print 'T: count_t = {}, max(T) = {}'.format( count_t_i, max(T_step1.vector().array())) print 'T: count_t = {}, min(T_DHCP) = {}'.format( count_t_i, min(T_sol_d[count_t_i].vector().array())) print 'T: count_t = {}, max(T_DHCP) = {}'.format( count_t_i, max(T_sol_d[count_t_i].vector().array())), '\n' T_old.assign(T_step1) #rename T_step1.rename('IHCP_T', 'temperature from IHCP') T_step1_f << (T_step1, t_i) count_t_i += 1 #storage T_step1_d[count_t_i] = do.Function(V) T_step1_d[count_t_i].vector()[:] = T_step1.vector().array() return T_step1_d
def __init__(self, fenics_2d_rve, **kwargs): """[summary] Parameters ---------- object : [type] [description] fenics_2d_rve : [type] [description] element : tuple or dict Type and degree of element for displacement FunctionSpace Ex: ('CG', 2) or {'family':'Lagrange', degree:2} solver : dict Choose the type of the solver, its method and the preconditioner. An up-to-date list of the available solvers and preconditioners can be obtained with dolfin.list_linear_solver_methods() and dolfin.list_krylov_solver_preconditioners(). """ self.rve = fenics_2d_rve self.topo_dim = topo_dim = fenics_2d_rve.dim try: bottom_left_corner = fenics_2d_rve.bottom_left_corner except AttributeError: logger.warning( "For the definition of the periodicity boundary conditions," "the bottom left corner of the RVE is assumed to be on (0.,0.)" ) bottom_left_corner = np.zeros(shape=(topo_dim, )) self.pbc = periodicity.PeriodicDomain.pbc_dual_base( fenics_2d_rve.gen_vect, "XY", bottom_left_corner, topo_dim) solver = kwargs.pop("solver", {}) # {'type': solver_type, 'method': solver_method, 'preconditioner': preconditioner} s_type = solver.pop("type", None) s_method = solver.pop("method", SOLVER_METHOD) s_precond = solver.pop("preconditioner", None) if s_type is None: if s_method in DOLFIN_KRYLOV_METHODS.keys(): s_type = "Krylov" elif s_method in DOLFIN_LU_METHODS.keys(): s_type = "LU" else: raise RuntimeError("The indicated solver method is unknown.") self._solver = dict(type=s_type, method=s_method) if s_precond: self._solver["preconditioner"] = s_precond element = kwargs.pop("element", ("Lagrange", 2)) if isinstance(element, dict): element = (element["family"], element["degree"]) self._element = element # * Function spaces cell = self.rve.mesh.ufl_cell() self.scalar_FE = fe.FiniteElement(element[0], cell, element[1]) self.displ_FE = fe.VectorElement(element[0], cell, element[1]) strain_deg = element[1] - 1 if element[1] >= 1 else 0 strain_dim = int(topo_dim * (topo_dim + 1) / 2) self.strain_FE = fe.VectorElement("DG", cell, strain_deg, dim=strain_dim) # Espace fonctionel scalaire self.X = fe.FunctionSpace(self.rve.mesh, self.scalar_FE, constrained_domain=self.pbc) # Espace fonctionnel 3D : deformations, notations de Voigt self.W = fe.FunctionSpace(self.rve.mesh, self.strain_FE) # Espace fonctionel 2D pour les champs de deplacement # TODO : reprendre le Ve défini pour l'espace fonctionnel mixte. Par ex: V = FunctionSpace(mesh, Ve) self.V = fe.VectorFunctionSpace(self.rve.mesh, element[0], element[1], constrained_domain=self.pbc) # * Espace fonctionel mixte pour la résolution : # * 2D pour les champs + scalaire pour multiplicateur de Lagrange # "R" : Real element with one global degree of freedom self.real_FE = fe.VectorElement("R", cell, 0) self.M = fe.FunctionSpace( self.rve.mesh, fe.MixedElement([self.displ_FE, self.real_FE]), constrained_domain=self.pbc, ) # Define variational problem self.v, self.lamb_ = fe.TestFunctions(self.M) self.u, self.lamb = fe.TrialFunctions(self.M) self.w = fe.Function(self.M) # bilinear form self.a = ( fe.inner(sigma(self.rve.C_per, epsilon(self.u)), epsilon(self.v)) * fe.dx + fe.dot(self.lamb_, self.u) * fe.dx + fe.dot(self.lamb, self.v) * fe.dx) self.K = fe.assemble(self.a) if self._solver["type"] == "Krylov": self.solver = fe.KrylovSolver(self.K, self._solver["method"]) elif self._solver["type"] == "LU": self.solver = fe.LUSolver(self.K, self._solver["method"]) self.solver.parameters["symmetric"] = True try: self.solver.parameters.preconditioner = self._solver[ "preconditioner"] except KeyError: pass # fe.info(self.solver.parameters, True) self.localization = dict() # dictionary of localization field objects, # will be filled up when calling auxiliary problems (lazy evaluation) self.ConstitutiveTensors = dict()
def __init__(self, m, parameters=None, degree=1, element="CG", project_method='magpar', unit_length=1, Ms=None, bench=False, normalize=True, solver_type=None): assert isinstance(m, Field) assert isinstance( Ms, Field ) # currently this means that Ms must be passed in (we don't have a default value) self.m = m # Problem objects and parameters self.name = "Demag" self.in_jacobian = False self.unit_length = unit_length self.degree = degree self.bench = bench self.parameters = parameters # This is used in energy density calculations self.mu0 = np.pi * 4e-7 # Vs/(Am) # Mesh Facet Normal self.n = df.FacetNormal(self.m.mesh()) # Spaces and functions for the Demag Potential self.V = df.FunctionSpace(self.m.mesh(), element, degree) self.v = df.TestFunction(self.V) self.u = df.TrialFunction(self.V) self.phi = df.Function(self.V) # Space and functions for the Demag Field self.W = df.VectorFunctionSpace(self.m.mesh(), element, degree, dim=3) self.w = df.TrialFunction(self.W) self.vv = df.TestFunction(self.W) self.H_demag = df.Function(self.W) # Interpolate the Unit Magentisation field if necessary # A try block was not used since it might lead to an unneccessary (and potentially bad) # interpolation # if isinstance(m, df.Expression) or isinstance(m, df.Constant): # self.m = df.interpolate(m,self.W) # elif isinstance(m,tuple): # self.m = df.interpolate(df.Expression(m, degree=1),self.W) # elif isinstance(m,list): # self.m = df.interpolate(df.Expression(tuple(m, degree=1)),self.W) # else: # self.m = m # Normalize m (should be normalized anyway). # if normalize: # self.m.vector()[:] = helpers.fnormalise(self.m.vector().array()) assert isinstance(Ms, Field) self.Ms = Ms # Initilize the boundary element matrix variable self.bem = None # Objects that are needed frequently for linear solves. self.poisson_matrix = self.build_poisson_matrix() self.laplace_zeros = df.Function(self.V).vector() # 2nd FEM. if parameters: method = parameters["laplace_solver"]["method"] pc = parameters["laplace_solver"]["preconditioner"] else: method, pc = "default", "default" if solver_type is None: solver_type = 'Krylov' solver_type = solver_type.lower() if solver_type == 'lu': self.laplace_solver = df.LUSolver() self.laplace_solver.parameters["reuse_factorization"] = True elif solver_type == 'krylov': self.laplace_solver = df.KrylovSolver(method, pc) # We're setting 'same_nonzero_pattern=True' to enforce the # same matrix sparsity pattern across different demag solves, # which should speed up things. #self.laplace_solver.parameters["preconditioner"][ # "structure"] = "same_nonzero_pattern" else: raise ValueError( "Wrong solver type specified: '{}' (allowed values: 'Krylov', 'LU')" .format(solver_type)) # Objects needed for energy density computation self.nodal_vol = df.assemble(self.v * df.dx).array() self.ED = df.Function(self.V) # Method to calculate the Demag field from the potential self.project_method = project_method if self.project_method == 'magpar': self.__setup_field_magpar() self.__compute_field = self.__compute_field_magpar elif self.project_method == 'project': self.__compute_field = self.__compute_field_project else: raise NotImplementedError("""Only methods currently implemented are * 'magpar', * 'project'""")
def solve_linear(self, d_outputs, d_residuals, mode): linear_solver_ = self.options['linear_solver_'] pde_problem = self.options['pde_problem'] state_name = self.options['state_name'] state_function = pde_problem.states_dict[state_name]['function'] for argument_name, argument_function in iteritems( self.argument_functions_dict): density_func = argument_function mesh = state_function.function_space().mesh() sub_domains = df.MeshFunction('size_t', mesh, mesh.topology().dim() - 1) upper_edge = TractionBoundary() upper_edge.mark(sub_domains, 6) dss = df.Measure('ds')(subdomain_data=sub_domains) tractionBC = dss(6) residual_form = get_residual_form( state_function, df.TestFunction(state_function.function_space()), density_func, density_func.function_space(), tractionBC, # df.Constant((0.0, -9.e-1)) df.Constant((0.0, -9.e-1)), int(self.itr)) A, _ = df.assemble_system(self.derivative_form, -residual_form, pde_problem.bcs_list) if linear_solver_ == 'fenics_direct': rhs_ = df.Function(state_function.function_space()) dR = df.Function(state_function.function_space()) rhs_.vector().set_local(d_outputs[state_name]) for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() AT = df.PETScMatrix(ATm) df.solve(AT, dR.vector(), rhs_.vector()) d_residuals[state_name] = dR.vector().get_local() elif linear_solver_ == 'scipy_splu': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() ATm_csr = csr_matrix(ATm.getValuesCSR()[::-1], shape=Am.size) lu = splu(ATm_csr.tocsc()) d_residuals[state_name] = lu.solve(d_outputs[state_name], trans='T') elif linear_solver_ == 'fenics_Krylov': rhs_ = df.Function(state_function.function_space()) dR = df.Function(state_function.function_space()) rhs_.vector().set_local(d_outputs[state_name]) for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() AT = df.PETScMatrix(ATm) solver = df.KrylovSolver('gmres', 'ilu') prm = solver.parameters prm["maximum_iterations"] = 1000000 prm["divergence_limit"] = 1e2 solver.solve(AT, dR.vector(), rhs_.vector()) d_residuals[state_name] = dR.vector().get_local() elif linear_solver_ == 'petsc_gmres_ilu': ksp = PETSc.KSP().create() ksp.setType(PETSc.KSP.Type.GMRES) ksp.setTolerances(rtol=5e-11) for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ksp.setOperators(Am) ksp.setFromOptions() pc = ksp.getPC() pc.setType("ilu") size = state_function.function_space().dim() dR = PETSc.Vec().create() dR.setSizes(size) dR.setType('seq') dR.setValues(range(size), d_residuals[state_name]) dR.setUp() du = PETSc.Vec().create() du.setSizes(size) du.setType('seq') du.setValues(range(size), d_outputs[state_name]) du.setUp() if mode == 'fwd': ksp.solve(dR, du) d_outputs[state_name] = du.getValues(range(size)) else: ksp.solveTranspose(du, dR) d_residuals[state_name] = dR.getValues(range(size))
def solve_linear(self, d_outputs, d_residuals, mode): option = self.options['option'] dR_du_sparse = self.dR_du_sparse if option==1: ksp = PETSc.KSP().create() ksp.setType(PETSc.KSP.Type.GMRES) ksp.setTolerances(rtol=5e-14) ksp.setOperators(dR_du_sparse) ksp.setFromOptions() pc = ksp.getPC() pc.setType("ilu") size = len(self.fea.VC.dofmap().dofs()) dR = PETSc.Vec().create() dR.setSizes(size) dR.setType('seq') dR.setValues(range(size), d_residuals['density']) dR.setUp() du = PETSc.Vec().create() du.setSizes(size) du.setType('seq') du.setValues(range(size), d_outputs['density']) du.setUp() if mode == 'fwd': ksp.solve(dR,du) d_outputs['density'] = du.getValues(range(size)) else: ksp.solveTranspose(du,dR) d_residuals['density'] = dR.getValues(range(size)) print('d_residual[density]', d_residuals['density']) elif option==2: # print('option 2') rhs_ = df.Function(self.function_space) dR = df.Function(self.function_space) rhs_.vector().set_local(d_outputs['density']) A = self.A Am = df.as_backend_type(A).mat() ATm = Am.transpose() AT = df.PETScMatrix(ATm) df.solve(AT,dR.vector(),rhs_.vector()) # cannot directly use fea.u here, the update for the solution is not compatible d_residuals['density'] = dR.vector().get_local() elif option==3: A = self.A Am = df.as_backend_type(A).mat() ATm = Am.transpose() ATm_csr = csr_matrix(ATm.getValuesCSR()[::-1], shape=Am.size) lu = splu(ATm_csr.tocsc()) d_residuals['density'] = lu.solve(d_outputs['density'],trans='T') elif option==4: rhs_ = df.Function(self.function_space) dR = df.Function(self.function_space) rhs_.vector().set_local(d_outputs['density']) A = self.A Am = df.as_backend_type(A).mat() ATm = Am.transpose() AT = df.PETScMatrix(ATm) df.set_log_active(True) solver = df.KrylovSolver('gmres', 'ilu') prm = solver.parameters prm["maximum_iterations"]=1000000 prm["divergence_limit"] = 1e2 # info(parameters,True) solver.solve(AT,dR.vector(),rhs_.vector()) d_residuals['displacements'] = dR.vector().get_local()
def setup(self, m, Ms, unit_length=1): self.m = m self.Ms = Ms self.unit_length = unit_length mesh = m.mesh() self.S1 = df.FunctionSpace(mesh, "Lagrange", 1) self.dim = mesh.topology().dim() self._test1 = df.TestFunction(self.S1) self._trial1 = df.TrialFunction(self.S1) self._test3 = df.TestFunction(self.m.functionspace) self._trial3 = df.TrialFunction(self.m.functionspace) # for computation of energy self._nodal_volumes = nodal_volume(self.S1, unit_length) # we will copy field into this when we need the energy self._H_func = df.Function(self.m.functionspace) self._E_integrand = -0.5 * mu0 * \ df.dot(self._H_func, self.m.f * self.Ms.f) self._E = self._E_integrand * df.dx self._nodal_E = df.dot(self._E_integrand, self._test1) * df.dx self._nodal_E_func = df.Function(self.S1) # for computation of field and scalar magnetic potential self._poisson_matrix = self._poisson_matrix() self._poisson_solver = df.KrylovSolver( self._poisson_matrix.copy(), self.parameters['phi_1_solver'], self.parameters['phi_1_preconditioner']) self._poisson_solver.parameters.update(self.parameters['phi_1']) self._laplace_zeros = df.Function(self.S1).vector() self._laplace_solver = df.KrylovSolver( self.parameters['phi_2_solver'], self.parameters['phi_2_preconditioner']) self._laplace_solver.parameters.update(self.parameters['phi_2']) # We're setting 'same_nonzero_pattern=True' to enforce the # same matrix sparsity pattern across different demag solves, # which should speed up things. self._laplace_solver.parameters["preconditioner"][ "structure"] = "same_nonzero_pattern" # solution of inhomogeneous Neumann problem self._phi_1 = df.Function(self.S1) # solution of Laplace equation inside domain self._phi_2 = df.Function(self.S1) self._phi = df.Function(self.S1) # magnetic potential phi_1 + phi_2 # To be applied to the vector field m as first step of computation of _phi_1. # This gives us div(M), which is equal to Laplace(_phi_1), equation # which is then solved using _poisson_solver. self._Ms_times_divergence = df.assemble( self.Ms.f * df.inner(self._trial3, df.grad(self._test1)) * df.dx) # we move the bounday condition here to avoid create a instance each time when compute the # magnetic potential self.boundary_condition = df.DirichletBC(self.S1, self._phi_2, df.DomainBoundary()) self.boundary_condition.apply(self._poisson_matrix) self._setup_gradient_computation() self.mesh = self.m.mesh() self.bmesh = df.BoundaryMesh(self.mesh, 'exterior', False) #self.b2g_map = self.bmesh.vertex_map().array() self._b2g_map = self.bmesh.entity_map(0).array() self.compute_triangle_normal() self.__compute_bsa() fast_sum = FastSum(p=self.p, mac=self.mac, num_limit=self.num_limit, correct_factor=self.correct_factor, type_I=self.type_I) coords = self.bmesh.coordinates() face_nodes = np.array(self.bmesh.cells(), dtype=np.int32) fast_sum.init_mesh(coords, self.t_normals, face_nodes, self.vert_bsa) self.fast_sum = fast_sum self.phi2_b = np.zeros(self.bmesh.num_vertices())
def solve_linear(self, d_outputs, d_residuals, mode): linear_solver_ = self.options['linear_solver_'] pde_problem = self.options['pde_problem'] state_name = self.options['state_name'] state_function = pde_problem.states_dict[state_name]['function'] residual_form = pde_problem.states_dict[state_name]['residual_form'] if state_name == 'density': print('this is a variational density filter') A, _ = df.assemble_system(self.derivative_form, -residual_form) else: A, _ = df.assemble_system(self.derivative_form, -residual_form, pde_problem.bcs_list) def report(xk): frame = inspect.currentframe().f_back if linear_solver_ == 'fenics_direct': rhs_ = df.Function(state_function.function_space()) dR = df.Function(state_function.function_space()) rhs_.vector().set_local(d_outputs[state_name]) if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() AT = df.PETScMatrix(ATm) df.solve(AT, dR.vector(), rhs_.vector()) d_residuals[state_name] = dR.vector().get_local() elif linear_solver_ == 'scipy_splu': if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() ATm_csr = csr_matrix(ATm.getValuesCSR()[::-1], shape=Am.size) lu = splu(ATm_csr.tocsc()) d_residuals[state_name] = lu.solve(d_outputs[state_name], trans='T') elif linear_solver_ == 'scipy_cg': if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() ATm_csr = csr_matrix(ATm.getValuesCSR()[::-1], shape=Am.size) # lu = splu(ATm_csr.tocsc()) b = d_outputs[state_name] x, info = splinalg.cg(ATm_csr, b, tol=1e-8, callback=report) print('the residual is:') print(info) d_residuals[state_name] = x elif linear_solver_ == 'fenics_krylov': rhs_ = df.Function(state_function.function_space()) dR = df.Function(state_function.function_space()) rhs_.vector().set_local(d_outputs[state_name]) if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() AT = df.PETScMatrix(ATm) solver = df.KrylovSolver('gmres', 'ilu') prm = solver.parameters prm["maximum_iterations"] = 1000000 prm["divergence_limit"] = 1e2 solver.solve(AT, dR.vector(), rhs_.vector()) # print('solve'+iter) d_residuals[state_name] = dR.vector().get_local() elif linear_solver_ == 'petsc_gmres_ilu': ksp = PETSc.KSP().create() ksp.setType(PETSc.KSP.Type.GMRES) ksp.setTolerances(rtol=5e-17) if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ksp.setOperators(Am) ksp.setFromOptions() pc = ksp.getPC() pc.setType("lu") size = state_function.function_space().dim() dR = PETSc.Vec().create() dR.setSizes(size) dR.setType('seq') dR.setValues(range(size), d_residuals[state_name]) dR.setUp() du = PETSc.Vec().create() du.setSizes(size) du.setType('seq') du.setValues(range(size), d_outputs[state_name]) du.setUp() if mode == 'fwd': ksp.solve(dR, du) d_outputs[state_name] = du.getValues(range(size)) else: ksp.solveTranspose(du, dR) d_residuals[state_name] = dR.getValues(range(size)) elif linear_solver_ == 'petsc_cg_ilu': ksp = PETSc.KSP().create() ksp.setType(PETSc.KSP.Type.CG) ksp.setTolerances(rtol=5e-15) if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ksp.setOperators(Am) ksp.setFromOptions() pc = ksp.getPC() pc.setType("lu") size = state_function.function_space().dim() dR = PETSc.Vec().create() dR.setSizes(size) dR.setType('seq') dR.setValues(range(size), d_residuals[state_name]) dR.setUp() du = PETSc.Vec().create() du.setSizes(size) du.setType('seq') du.setValues(range(size), d_outputs[state_name]) du.setUp() if mode == 'fwd': ksp.solve(dR, du) d_outputs[state_name] = du.getValues(range(size)) else: ksp.solveTranspose(du, dR) d_residuals[state_name] = dR.getValues(range(size))
import dolfin as d import vtk print(vtk.VTK_VERSION) dump_file = d.HDF5File(d.mpi_comm_world(), 'test.h5', 'w') dump_file_2 = d.File('test.xml.gz') solver = d.KrylovSolver("cg", "hypre_amg") mesh = d.UnitCubeMesh(10, 10, 10) V = d.FunctionSpace(mesh, "CG", 2) phi = d.Function(V) dump_file.write(phi, 'phi_func') dump_file.close() dump_file_2 << phi
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
def setup(self, DG3, m, Ms, unit_length=1): """ Setup the FKDemag instance. Usually called automatically by the Simulation object. *Arguments* S3: dolfin.VectorFunctionSpace The finite element space the magnetisation is defined on. m: dolfin.Function on S3 The unit magnetisation. Ms: float The saturation magnetisation in A/m. unit_length: float The length (in m) represented by one unit on the mesh. Default 1. """ self.m = m self.Ms = Ms self.unit_length = unit_length mesh = DG3.mesh() self.S1 = df.FunctionSpace(mesh, "Lagrange", 1) self.S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1) self.dim = mesh.topology().dim() self.n = df.FacetNormal(mesh) self.DG3 = DG3 self._test1 = df.TestFunction(self.S1) self._trial1 = df.TrialFunction(self.S1) self._test3 = df.TestFunction(self.S3) self._trial3 = df.TrialFunction(self.S3) self._test_dg3 = df.TestFunction(self.DG3) self._trial_dg3 = df.TrialFunction(self.DG3) # for computation of energy self._nodal_volumes = nodal_volume(self.S1, unit_length) self._H_func = df.Function( DG3) # we will copy field into this when we need the energy self._E_integrand = -0.5 * mu0 * df.dot(self._H_func, self.m * self.Ms) self._E = self._E_integrand * df.dx self._nodal_E = df.dot(self._E_integrand, self._test1) * df.dx self._nodal_E_func = df.Function(self.S1) # for computation of field and scalar magnetic potential self._poisson_matrix = self._poisson_matrix() self._poisson_solver = df.KrylovSolver( self._poisson_matrix, self.parameters['phi_1_solver'], self.parameters['phi_1_preconditioner']) self._poisson_solver.parameters.update(self.parameters['phi_1']) self._laplace_zeros = df.Function(self.S1).vector() self._laplace_solver = df.KrylovSolver( self.parameters['phi_2_solver'], self.parameters['phi_2_preconditioner']) self._laplace_solver.parameters.update(self.parameters['phi_2']) self._laplace_solver.parameters["preconditioner"][ "same_nonzero_pattern"] = True with fk_timed('compute BEM'): if not hasattr(self, "_bem"): self._bem, self._b2g_map = compute_bem_fk( df.BoundaryMesh(mesh, 'exterior', False)) self._phi_1 = df.Function( self.S1) # solution of inhomogeneous Neumann problem self._phi_2 = df.Function( self.S1) # solution of Laplace equation inside domain self._phi = df.Function(self.S1) # magnetic potential phi_1 + phi_2 # To be applied to the vector field m as first step of computation of _phi_1. # This gives us div(M), which is equal to Laplace(_phi_1), equation # which is then solved using _poisson_solver. self._Ms_times_divergence = df.assemble( self.Ms * df.inner(self._trial_dg3, df.grad(self._test1)) * df.dx) self._setup_gradient_computation()
def setup(self, m, Ms, unit_length=1): """ Setup the FKDemag instance. Usually called automatically by the Simulation object. *Arguments* m: finmag.Field The unit magnetisation on a finite element space. Ms: float The saturation magnetisation in A/m. unit_length: float The length (in m) represented by one unit on the mesh. Default 1. """ assert isinstance(m, Field) assert isinstance(Ms, Field) self.m = m self.Ms = Ms self.unit_length = unit_length self.S1 = df.FunctionSpace(self.m.mesh(), "Lagrange", 1) self._test1 = df.TestFunction(self.S1) self._trial1 = df.TrialFunction(self.S1) self._test3 = df.TestFunction(self.m.functionspace) self._trial3 = df.TrialFunction(self.m.functionspace) # for computation of energy self._nodal_volumes = nodal_volume(self.S1, unit_length) self._H_func = df.Function(m.functionspace) # we will copy field into # this when we need the # energy self._E_integrand = -0.5 * mu0 * \ df.dot(self._H_func, self.m.f * self.Ms.f) self._E = self._E_integrand * df.dx self._nodal_E = df.dot(self._E_integrand, self._test1) * df.dx self._nodal_E_func = df.Function(self.S1) # for computation of field and scalar magnetic potential self._poisson_matrix = self._poisson_matrix() self._laplace_zeros = df.Function(self.S1).vector() # determine the solver type to be used (Krylov or LU); if the kwarg # 'solver_type' is not provided, try to read the setting from the # .finmagrc file; use 'Krylov' if this fails. solver_type = self.solver_type if solver_type is None: solver_type = configuration.get_config_option( 'demag', 'solver_type', 'Krylov') if solver_type == 'None': # if the user set 'solver_type = None' in # the .finmagrc file, solver_type will be a # string so we need to catch this here. solver_type = 'Krylov' logger.debug("Using {} solver for demag.".format(solver_type)) if solver_type == 'Krylov': self._poisson_solver = df.KrylovSolver( self._poisson_matrix.copy(), self.parameters['phi_1_solver'], self.parameters['phi_1_preconditioner']) self._poisson_solver.parameters.update(self.parameters['phi_1']) self._laplace_solver = df.KrylovSolver( self.parameters['phi_2_solver'], self.parameters['phi_2_preconditioner']) self._laplace_solver.parameters.update(self.parameters['phi_2']) # We're setting 'same_nonzero_pattern=True' to enforce the # same matrix sparsity pattern across different demag solves, # which should speed up things. #self._laplace_solver.parameters["preconditioner"][ # "structure"] = "same_nonzero_pattern" elif solver_type == 'LU': self._poisson_solver = df.LUSolver(self._poisson_matrix.copy()) self._laplace_solver = df.LUSolver() self._poisson_solver.parameters["reuse_factorization"] = True self._laplace_solver.parameters["reuse_factorization"] = True else: raise ValueError( "Argument 'solver_type' must be either 'Krylov' or 'LU'. " "Got: '{}'".format(solver_type)) with fk_timer('compute BEM'): if not hasattr(self, "_bem"): if self.macrogeometry is not None: Ts = self.macrogeometry.compute_Ts(self.m.mesh()) pbc = BMatrixPBC(self.m.mesh(), Ts) self._b2g_map = np.array(pbc.b2g_map, dtype=np.int) self._bem = pbc.bm else: self._bem, self._b2g_map = compute_bem_fk( df.BoundaryMesh(self.m.mesh(), 'exterior', False)) logger.debug( "Boundary element matrix uses {:.2f} MB of memory.".format( self._bem.nbytes / 1024.**2)) # solution of inhomogeneous Neumann problem self._phi_1 = df.Function(self.S1) # solution of Laplace equation inside domain self._phi_2 = df.Function(self.S1) self._phi = df.Function(self.S1) # magnetic potential phi_1 + phi_2 # To be applied to the vector field m as first step of computation of # _phi_1. This gives us div(M), which is equal to Laplace(_phi_1), # equation which is then solved using _poisson_solver. self._Ms_times_divergence = df.assemble( self.Ms.f * df.inner(self._trial3, df.grad(self._test1)) * df.dx) # we move the boundary condition here to avoid create a instance each # time when compute the magnetic potential self.boundary_condition = df.DirichletBC(self.S1, self._phi_2, df.DomainBoundary()) self.boundary_condition.apply(self._poisson_matrix) self._setup_gradient_computation()
(v, q) = df.TestFunctions(W) f = df.Constant((0.0, 0.0)) # right hand side a = mu * df.inner(df.grad(u), df.grad(v)) * df.dx + df.div(v) * p * df.dx + q * df.div(u) * df.dx L = df.inner(f, v) * df.dx # Form for use in constructing preconditioner matrix b = df.inner(df.grad(u), df.grad(v)) * df.dx + p * q * df.dx # Assemble system A, bb = df.assemble_system(a, L, bcs) # Assemble preconditioner system P, btmp = df.assemble_system(b, L, bcs) # Create Krylov solver and AMG preconditioner solver = df.KrylovSolver(krylov_method, 'amg') # Associate operator (A) and preconditioner matrix (P) solver.set_operators(A, P) # Solve print('Solving PDE...') t = time.time() U = df.Function(W) #this should go fast up to here, so let's flush before solving the PDE sys.stdout.flush() try: solver.solve(U.vector(), bb) elapsed_time = time.time() - t