def compute(prms): ''' Pennes equattion solver author: Felipe Galarce email: [email protected] ''' from functions.inout import readmesh import os.path import numpy as np import time import sys dim = 1 non_linear = 1 k = 0.5 cb = 3900 wb = 1.159 Qm = 1091 Ta = 37 if prms['options']['dim'] == 2: results_dir = prms['io']['results'] mesh_file = './meshes/' + prms['io']['mesh'] + '.h5' mesh, subdomains, boundaries = readmesh(mesh_file) # Characterize boundaries ds = Measure('ds', domain=mesh , subdomain_data=boundaries) else: mesh = IntervalMesh(10, 0, 4) V = FunctionSpace(mesh, "CG", 1) # variational form u, v = TrialFunction(V), TestFunction(V) T = Function(V) a = inner(k*grad(u), grad(v))*dx - cb*wb*inner(u, v)*dx L = inner(Qm, v)*dx - cb*wb*inner(Ta, v)*dx if prms['options']['dim'] == 2: bc = DirichletBC(V, 40.0, boundaries, 1) else: bc = DirichletBC(V, 40.0, 'on_boundary') solve(a == L, T, bc, solver_parameters={"linear_solver": "mumps"}, form_compiler_parameters={"optimize": True}) plot(T) interactive()
def compute(prms): ''' Stokes stationary flow equation solver author: Felipe Galarce email: [email protected] ''' from functions.inout import readmesh # Extract parameters mesh_file = prms['io']['mesh'] results_dir = prms['io']['results'] sol,prec = prms['num']['krylov'] mu = prms['phys']['mu'] g_inx = prms['phys']['g_inx'] # Mesh partitioner for parallel distributed systems #parameters['mesh_partitioner'] = 'ParMETIS' # default: SCOTCH if prms['num']['dry'] == True: # perform DRY RUN (e.g. if FFC fails on cluster) # disable time stepping and vtk output of initial condition T = -1 prms['io']['vtk'] = 0 print("--> PERFORMING DRY RUN") # Read mesh, boundaries and subdomains mesh, boundaries, subdomains = readmesh(mesh_file) # Define function spaces P1 = VectorFunctionSpace(mesh, "Lagrange", 1) B = VectorFunctionSpace(mesh, "Bubble", 4) V = P1 + B Q = FunctionSpace(mesh, "CG", 1) Mini = V*Q # DC condition over artery walls ("adhesion > cohesion") noslip = project(Constant((0, 0, 0)), V) bc = DirichletBC(Mini.sub(0), noslip, subdomains, 2) # Mark UFL variable with boundaries ds = Measure('ds', domain=mesh , subdomain_data=subdomains) # Define variational problem (u, p) = TrialFunctions(Mini) (v, q) = TestFunctions(Mini) f = Constant((0, 0, 0)) a = (mu*inner(grad(u), grad(v)) - div(v)*p + q*div(u))*dx L = inner(f, v)*dx + inner(Constant((0,g_inx,0)), v)*ds(1) # Compute solution w = Function(Mini) rank = mesh.mpi_comm().Get_rank() if prec == 'none': solve(a == L, w, bc, solver_parameters={'linear_solver': sol}) else: solve(a == L, w, bc, solver_parameters={'linear_solver': sol, 'preconditioner': prec}) # Split the mixed solution using a shallow copy (u, p) = w.split() if prms['io']['vtk'] == 1: ufile_pvd = File(results_dir + "/velocity.pvd") ufile_pvd << u pfile_pvd = File(results_dir + "/pressure.pvd") pfile_pvd << p
def compute(prms): ''' Pennes equattion solver author: Felipe Galarce email: [email protected] ''' from functions.inout import readmesh import os.path import numpy as np import time import sys # Extract parameters mesh_file = './meshes/' + prms['io']['mesh'] + '.h5' results_dir = prms['io']['results'] dt = float(prms['num']['dt']) T = float(prms['num']['T']) # # Parameters for Penne's equation # rho = float(prms['phys']['rho']) # rhob = float(prms['phys']['rhob']) # c = float(prms['phys']['c']) # cb = float(prms['phys']['cb']) # k_tissue = float(prms['phys']['k_tissue']) # k_blood = float(prms['phys']['k_blood']) # Ta = float(prms['phys']['Ta']) Tc_min = float(prms['phys']['Tc_min']) Tc_max = float(prms['phys']['Tc_max']) # wb = float(prms['phys']['wb']) # Tf = float(prms['phys']['Tf']) # hf = float(prms['phys']['hf']) # # Qm_mode = prms['phys']['Qm_mode'] # w_mode = prms['phys']['w_mode'] Tmax = prms['phys']['Tmax'] Tcr = prms['phys']['Tcr'] wb00 = prms['phys']['wb00'] wmax = prms['phys']['wmax'] # if Qm_mode == 'constant': ## Q_meta = float(33800) # Configuring form compiler # parameters["form_compiler"]["quadrature_degree"] = 6 parameters["form_compiler"]["optimize"] = True parameters["form_compiler"]["representation"] = 'quadrature' ## Read mesh, boundaries and subdomains, but first check if the mesh file exists if not os.path.isfile(mesh_file): import subprocess subprocess.call("cp ./meshes/" + prms['io']['mesh'] + ".geo ./", shell=True) subprocess.call("cp ./functions/xml2hdf5.py ./", shell=True) subprocess.call("gmsh -2 " + prms['io']['mesh'] + ".geo", shell=True) subprocess.call("dolfin-convert ./" + prms['io']['mesh'] + ".msh ./" + prms['io']['mesh'] + ".xml ", shell=True) subprocess.call("python xml2hdf5.py " + prms['io']['mesh'] + ".xml ", shell=True) subprocess.call("cp " + prms['io']['mesh'] + ".h5 ./meshes/", shell=True) subprocess.call("rm ./" + prms['io']['mesh'] + ".msh ./" + prms['io']['mesh'] + ".h5 ./" + prms['io']['mesh'] + ".xml ./" + prms['io']['mesh'] + "tissue_box_facet_region.xml " + prms['io']['mesh'] + "_physical_region.xml", shell=True) mesh, subdomains, boundaries = readmesh(mesh_file) # Characterize boundaries ds = Measure('ds', domain=mesh , subdomain_data=boundaries) # variational form V = FunctionSpace(mesh, "CG", 1) phi, v = TrialFunction(V), TestFunction(V) phi0, phit = interpolate(Constant(prms['phys']['T_inicial']), V), Function(V) plot(mesh) interactive() k = 0.5 cb = 3900 wb = Function(V) Qm = Function(V) Ta = 37 k_blood = 0.5 k_tissue = 0.5 rho = 1060 a = rho*cb/dt*inner(phi, v)*dx + inner(k_blood*grad(phi), grad(v))*dx(0) + inner(k_tissue*grad(phi), grad(v))*dx(1) L = rho*cb/dt*inner(phi0, v)*dx - inner(wb*cb*(Ta), v)*dx - inner(Qm, v)*dx + cb*inner(wb*phi0, v)*dx # Assemble LHS A = assemble(a) # boundary condition avg_temp = (Tc_max + Tc_min)/2; Amp = (Tc_max - Tc_min)/2 T_boundary = Expression(str(avg_temp) + ' + ' + str(Amp) + '*sin(t/4)' , t = 0) def HS(x): # Heavy-Side function return (x > 0).astype(float) bc = DirichletBC(V, T_boundary, boundaries, 1) solver = LinearSolver('mumps') phi_file = File(results_dir + "/temperature.pvd") rank = mesh.mpi_comm().Get_rank() t = dt def Qm_exp(T): T_arr = T.vector().array() exponente = (T_arr- 37)/10 dos = 2*np.ones(len(T_arr)) Q = 0.17*np.power(dos, exponente) # Q = 0.1178*(T_arr - 37) + 0.17 return Q # mesh dimension and dofmap gdim = mesh.geometry().dim() dofmap = V.dofmap(); dofs = dofmap.dofs() def Wb_(T): T_arr = T.vector().array(); wb.vector()[:] = wb00*HS(Tcr - T_arr) + (wmax + wb00)/2*HS(T_arr - Tmax) + wmax*(1 + ((wmax - wb00)/wb00)*((T_arr - Tcr)/(Tmax - Tcr)))*(1 - HS(T_arr - Tmax) - HS(Tcr - T_arr)) return wb start_time = time.time() while t <= T + dt: progress = float(t)/float(T + dt)*100.0; time_elapsed = time.time() - start_time print '\r --> %.2f [ms] | %.0f %% | computing-time-elapsed = %.2f [seg] ' % (t, progress, time_elapsed), sys.stdout.flush() # --> SOLVING PENNE'S EQUATION # assemble RHS wb = Wb_(phi0) Qm.vector()[:] = Qm_exp(phi0) b = assemble(L) # apply Dirichlet boundary conditions T_boundary.t = t; bc.apply(A, b) # solve linear system solve(A, phit.vector(), b) # save solution to file phi_file << phi0 phi0.assign(phit) t += dt
def compute(prms): ''' monodomain+minimal equation solver author: Felipe Galarce email: [email protected] ''' from functions.inout import readmesh # Extract parameters results_dir = prms['io']['results'] dt = prms['num']['dt'] sol_method, prec, solh_method, prech = prms['num']['krylov'] deg = prms['num']['deg'] n = prms['num']['n'] part = prms['phys']['part'] est1_intensity, est1_delay, est1_duration = prms['phys']['est1'] est2_intensity, est2_delay, est2_duration = prms['phys']['est2'] phi_i, r_i, w_i, s_i = prms['phys']['initial_conditions'] T = prms['phys']['T'] sigma_1 = prms['phys']['sigma_1'] betha = prms['phys']['betha']; gamma = prms['phys']['gamma'] amount_fibrosis = prms['phys']['amount_fibrosis'] e1x, e1y = prms['phys']['lamination_direction_main'] e2x, e2y = prms['phys']['lamination_direction_cross'] e1 = Constant((e1x, e1y)); e2 = Constant((e2x, e2y)); b, h = prms['phys']['b'], prms['phys']['h'] # TODO: erase only error and benchmark before simulation if exist previously if prms['io']['xdmf'] == 1: # TODO: output function sol = File(results_dir+"/sol.xdmf") solh = File(results_dir+"/solh.xdmf") error = open(results_dir + "/error_L2", 'w+') benchmark = open(results_dir + "/benchmark", 'w+') # Import minimal model parameters if part == 'endo': mat = sio.loadmat('./input/minimal_parameters_endo.mat') elif part == 'epi': mat = sio.loadmat('./input/minimal_parameters_epi.mat') else: mat = sio.loadmat('./input/minimal_parameters_mid.mat') p1_phi0 = float(mat['p1_phi0'][0,0]) p2_phiu = float(mat['p2_phiu'][0,0]) p3_thetav = float(mat['p3_thetav'][0,0]) p4_thetaw = float(mat['p4_thetaw'][0,0]) p5_thetav_minus = float(mat['p5_thetav_minus'][0,0]) p6_theta_0 = float(mat['p6_theta_0'][0,0]) p7_tauv1_minus = float(mat['p7_tauv1_minus'][0,0]) p8_tauv2_minus = float(mat['p8_tauv2_minus'][0,0]) p9_tauv_plus = float(mat['p9_tauv_plus'][0,0]) p10_tauw1_minus = float(mat['p10_tauw1_minus'][0,0]) p11_tauw2_minus = float(mat['p11_tauw2_minus'][0,0]) p12_kw_minus = float(mat['p12_kw_minus'][0,0]) p13_phiw_minus = float(mat['p13_phiw_minus'][0,0]) p14_tau_w_plus = float(mat['p14_tau_w_plus'][0,0]) p15_tau_fi = float(mat['p15_tau_fi'][0,0]) p16_tau_o1 = float(mat['p16_tau_o1'][0,0]) p17_tau_o2 = float(mat['p17_tau_o2'][0,0]) p18_tau_so1 = float(mat['p18_tau_so1'][0,0]) p19_tau_so2 = float(mat['p19_tau_so2'][0,0]) p20_k_so = float(mat['p20_k_so'][0,0]) p21_phi_so = float(mat['p21_phi_so'][0,0]) p22_tau_s1 = float(mat['p22_tau_s1'][0,0]) p23_tau_s2 = float(mat['p23_tau_s2'][0,0]) p24_ks = float(mat['p24_ks'][0,0]) p25_phi_s = float(mat['p25_phi_s'][0,0]) p26_tau_si = float(mat['p26_tau_si'][0,0]) p27_tauw_inf = float(mat['p27_tauw_inf'][0,0]) p28_w_inf = float(mat['p28_w_inf'][0,0]) # Mesh partitioner for parallel distributed systems # TODO: enable PARMETIS (preguntar a david!) #parameters['mesh_partitioner'] = 'ParMETIS' # default: SCOTCH # NOTE: parmetis was optimized on the NLHPC cluster if prms['num']['dry'] == True: # perform DRY RUN (e.g. if FFC fails on cluster) # disable time stepping and vtk output of initial condition T = -1 prms['io']['vtk'] = 0 print("PERFORMING DRY RUN") def HS(x): # Heavy-Side function return (x > 0).astype(float) class DiscontinuousTensor(Expression):# Class with methods to assign tensors to its respective materials def __init__(self, cell_function, tensors): self.cell_function = cell_function self.coeffs = tensors def value_shape(self): return (2,2) def eval_cell(self, values, x, cell): subdomain_id = self.cell_function[cell.index] local_coeff = self.coeffs[subdomain_id] local_coeff.eval_cell(values, x, cell) # Class with subdomains to mark borders of the domain class Left(SubDomain): def inside(self, x, on_boundary): return near(x[0], 0.0) class Right(SubDomain): def inside(self, x, on_boundary): return near(x[0], b) class Bottom(SubDomain): def inside(self, x, on_boundary): return near(x[1], 0.0) class Top(SubDomain): def inside(self, x, on_boundary): return near(x[1], h) # Read mesh, boundaries and subdomains mesh, boundaries, subdomains = readmesh('./meshes/' + amount_fibrosis + '/mesh.h5') # mesh for homogenized problem TODO: deducir b y h desde malla exacta para quitarlos de archivo input mesh_h = RectangleMesh(Point(0.0, 0.0), Point(b, h), n, n, "crossed") if amount_fibrosis == 'high_fibrosis': theta_c = 0.4 # proportion of colaggen over the rest of the domain (0.05 healthy, 0.15 moderated y 0.4 high) theta_f = 0.5 # proportion of fiber over the rest of the domain elif amount_fibrosis == 'square': theta_c = 0 theta_f = 0 mesh = UnitSquareMesh(3,3) mesh_h, boundaries, subdomains = readmesh('./meshes/' + amount_fibrosis + '/mesh.h5') # Define P1-Lagrange function spaces over meshes V = FunctionSpace(mesh, "CG", prms['num']['deg']) Vh = FunctionSpace(mesh_h, "CG", prms['num']['deg']) # function space for test and trial functions cf = CellFunction("size_t", mesh) # check if subdomains file exist if os.path.isfile('./meshes/' + amount_fibrosis + '/subdomains.h5'): # Import indicatrix function over exact mesh in order to mark fibrotic tissue cf_file = HDF5File(mesh.mpi_comm(), './meshes/' + amount_fibrosis + '/subdomains.h5', "r") cf_file.read(cf, "/cf") cf_file.close() # ****************************************** # Define difusion tensors for both healthy and fibrotic tissue sigma_c, sigma_2 = betha*sigma_1, sigma_1/gamma # diffusivity for colagen and cross fibers (sigma_2) Dh = Constant(((sigma_1, 0), # healthy diffusion tensor (0, sigma_2))) Dcol = Constant(((sigma_c*1 , 0.0,), # collagen diffusion tensor (0.0, sigma_c*1))) vals = np.zeros(2) Dh.eval(vals, np.zeros(3)) print vals # TODO: search for a more convenient form of obtain a component from a ufl constant tensor D11 = inner(dot(Dh, Constant((1.0, 0))), Constant((1.0, 0))) print D11 plot(mesh) interactive() # Calculate effective tensor for homogenized problem Deffp = theta_c*Dcol + (1 - theta_c)*Dh - (outer(theta_c*(1 - theta_c)*(Dcol - Dh)*e1, (Dcol - Dh).T*e1))/((1 - theta_c)*inner((Dcol*e1), e1) + theta_c*inner((Dh*e1), e1)) i, j = 0, 0; Deffpij = Deffp[i,j]; Deff = theta_f*Deffp + (1 - theta_f)*Dh - (outer(theta_f*(1 - theta_f)*(Deffp - Dh)*e2, (Deffp - Dh).T*e2))/((1 - theta_f)*inner((Deffp*e2), e2) + theta_f*inner((Dh*e2), e2)) i, j = 0, 0; Deffij = Deff[i,j]; C = DiscontinuousTensor(cf, [Dh, Dcol]) # Assign tensors where they belongs # ****************************************** # Initialize sub-domain instances left = Left() top = Top() right = Right() bottom = Bottom() right.b = b; top.h = h; # Mark boundaries of the domain boundaries = FacetFunction("size_t", mesh) boundaries.set_all(0) left.mark(boundaries, 1) top.mark(boundaries, 2) right.mark(boundaries, 3) bottom.mark(boundaries, 4) boundaries_h = FacetFunction("size_t", mesh_h) boundaries_h.set_all(0) left.mark(boundaries_h, 1) top.mark(boundaries_h, 2) right.mark(boundaries_h, 3) bottom.mark(boundaries_h, 4) # ****************************************** # Initial conditions phi1, r1, w1, s1 = interpolate(Expression(str(phi_i)), V ), interpolate(Expression(str(r_i)), V ), interpolate(Expression(str(w_i)), V ), interpolate(Expression(str(s_i)), V) phi1h, r1h, w1h, s1h = interpolate(Expression(str(phi_i)), Vh), interpolate(Expression(str(r_i)), Vh), interpolate(Expression(str(w_i)), Vh), interpolate(Expression(str(s_i)), Vh) # ****************************************** # Inward and outward currents factorization J, J_h = Function(V), Function(Vh) # Continuous variational exact problem u, v = TrialFunction(V), TestFunction(V) a_K = inner(C * nabla_grad(u), nabla_grad(v)) * dx a_M = u*v*dx # Continuous Variational Homogenized Problem uh, vh = TrialFunction(Vh), TestFunction(Vh) a_Kh = inner(Deff * grad(uh), grad(vh)) * dx a_Mh = uh*vh*dx # Assemble stifness and mass matrix for discretized variational problem start = time.time() K = assemble(a_K) M = assemble(a_M) A = M + dt*K end = time.time() time_assembly = end - start # Assemble stifness and mass matrix for discretized variational homogenized problem start = time.time() Kh = assemble(a_Kh) Mh = assemble(a_Mh) Ah = Mh + dt*Kh end = time.time() time_assembly_h = end - start benchmark.write(str(time_assembly) + " " + str(time_assembly_h) + "\n") phi, phih, F_k, F_kh = Function(V), Function(Vh), Function(V), Function(Vh) # ****************************************** # Auxiliar vectors of the ufl-functions in order to get element-wise operations r1_arr, w1_arr, s1_arr = r1.vector().array(), w1.vector().array(), s1.vector().array() r1h_arr, w1h_arr, s1h_arr = r1h.vector().array(), w1h.vector().array(), s1h.vector().array() # Auxiliary functions to save and export re-scaled potential aux_out1, aux_out2 = Function(V), Function(Vh) # ****************************************** # External stimulus (the values of g have to be different to obtain the same stimula in both exact and homogenized tissue) g1 = Expression('-est1_intensity' , est1_intensity=est1_intensity) g2 = Expression('-est2_intensity', est2_intensity=est2_intensity) g1h = Expression('-est1_intensity', est1_intensity=est1_intensity) g2h = Expression('-est2_intensity', est2_intensity=est2_intensity) ds = Measure('ds', domain=mesh , subdomain_data=boundaries ) ds_h = Measure('ds', domain=mesh_h, subdomain_data=boundaries_h) # ****************************************** # Time - loop # Init Krylov solvers if prec != 'none' and prech == 'none': solver, solverh = KrylovSolver(sol_method, prec), KrylovSolver(solh_method) elif prec != 'none' and prech != 'none': solver, solverh = KrylovSolver(sol_method, prec), KrylovSolver(solh_method, prech) elif prec == 'none' and prech == 'none': solver, solverh = KrylovSolver(sol_method), KrylovSolver(solh_method) elif prec == 'none' and prech != 'none': solver, solverh = KrylovSolver(sol_method), KrylovSolver(solh_method, prech) # the following prevent to evaluate conditional every time-step if prms['io']['xdmf'] == 1: counter = 10 else: counter = 11 rank = mesh.mpi_comm().Get_rank() t = dt while t < T: if rank == 0: print "solving time step t = %g" % t #*********************************** # Solving EDO's (Exact Problem) # Update arrays phi1_arr = phi1.vector().array() phi1h_arr = phi1h.vector().array() eq1 = (1 - HS(phi1_arr - p5_thetav_minus)*p7_tauv1_minus + HS(phi1_arr - p5_thetav_minus)*p8_tauv2_minus); eq2 = p10_tauw1_minus + (p11_tauw2_minus - p10_tauw1_minus)*(1 + np.tanh(p12_kw_minus*(phi1_arr - p13_phiw_minus)))/2; eq3 = p18_tau_so1 + (p19_tau_so2 - p18_tau_so1)*(1 + np.tanh(p20_k_so*(phi1_arr - p21_phi_so)))/2; eq4 = (1 - HS(phi1_arr - p4_thetaw))*p22_tau_s1 + HS(phi1_arr - p4_thetaw)*p23_tau_s2; eq5 = (1 - HS(phi1_arr - p6_theta_0))*p16_tau_o1 + HS(phi1_arr - p6_theta_0)*p17_tau_o2; r_inf = (phi1_arr < p5_thetav_minus).astype(float); w_inf = (1 - HS(phi1_arr - p6_theta_0))*(1 - phi1_arr/p27_tauw_inf) + HS(phi1_arr - p6_theta_0)*p28_w_inf; # Update gating variables r1_arr = (r1_arr + (dt*r_inf*(1 - HS(phi1_arr - p3_thetav)))/eq1)/(1 + (dt*(1 - HS(phi1_arr - p3_thetav)))/eq1 + (dt*HS(phi1_arr - p3_thetav))/p9_tauv_plus); w1_arr = (w1_arr + (dt*w_inf*(1 - HS(phi1_arr - p4_thetaw)))/eq2)/(1 + (dt*(1 - HS(phi1_arr - p4_thetaw)))/eq2 + (dt*HS(phi1_arr - p4_thetaw))/p14_tau_w_plus); s1_arr = (s1_arr + (dt*(1 + np.tanh(p24_ks*(phi1_arr - p25_phi_s)))/2)/eq4) / (1 + dt/eq4); # Current factorization Jfi_i = -1/p15_tau_fi*r1_arr*HS(phi1_arr - p3_thetav) * (p2_phiu - phi1_arr + p3_thetav); Jfi_e = -r1_arr*HS(phi1_arr - p3_thetav)*p3_thetav*p2_phiu/p15_tau_fi; Jso_i = (1 - HS(phi1_arr - p4_thetaw))/eq5; Jso_e = HS(phi1_arr - p4_thetaw)/eq3 - p1_phi0/eq5*(1 - HS(phi1_arr - p4_thetaw)); Jsi_e = -HS(phi1_arr - p4_thetaw)*w1_arr*s1_arr/p26_tau_si; J.vector()[:]= Jsi_e + Jso_e + Jfi_e + (Jfi_i + Jso_i)*phi1_arr # Solving EDO's (Homogenized Problem) eq1 = (1 - HS(phi1h_arr - p5_thetav_minus)*p7_tauv1_minus + HS(phi1h_arr - p5_thetav_minus)*p8_tauv2_minus); eq2 = p10_tauw1_minus + (p11_tauw2_minus - p10_tauw1_minus)*(1 + np.tanh(p12_kw_minus*(phi1h_arr - p13_phiw_minus)))/2; eq3 = p18_tau_so1 + (p19_tau_so2 - p18_tau_so1)*(1 + np.tanh(p20_k_so*(phi1h_arr - p21_phi_so)))/2; eq4 = (1 - HS(phi1h_arr - p4_thetaw))*p22_tau_s1 + HS(phi1h_arr - p4_thetaw)*p23_tau_s2; eq5 = (1 - HS(phi1h_arr - p6_theta_0))*p16_tau_o1 + HS(phi1h_arr - p6_theta_0)*p17_tau_o2; r_inf = (phi1h_arr < p5_thetav_minus).astype(float); w_inf = (1 - HS(phi1h_arr - p6_theta_0))*(1 - phi1h_arr/p27_tauw_inf) + HS(phi1h_arr - p6_theta_0)*p28_w_inf; # Update gating variables r1h_arr = (r1h_arr + (dt*r_inf*(1 - HS(phi1h_arr - p3_thetav)))/eq1)/(1 + (dt*(1 - HS(phi1h_arr - p3_thetav)))/eq1 + (dt*HS(phi1h_arr - p3_thetav))/p9_tauv_plus); w1h_arr = (w1h_arr + (dt*w_inf*(1 - HS(phi1h_arr - p4_thetaw)))/eq2)/(1 + (dt*(1 - HS(phi1h_arr - p4_thetaw)))/eq2 + (dt*HS(phi1h_arr - p4_thetaw))/p14_tau_w_plus); s1h_arr = (s1h_arr + (dt*(1 + np.tanh(p24_ks*(phi1h_arr - p25_phi_s)))/2)/eq4) / (1 + dt/eq4); # Current factorization Jfi_i = -1/p15_tau_fi*r1h_arr*HS(phi1h_arr - p3_thetav) * (p2_phiu - phi1h_arr + p3_thetav); Jfi_e = -r1h_arr*HS(phi1h_arr - p3_thetav)*p3_thetav*p2_phiu/p15_tau_fi; Jso_i = (1 - HS(phi1h_arr - p4_thetaw))/eq5; Jso_e = HS(phi1h_arr - p4_thetaw)/eq3 - p1_phi0/eq5*(1 - HS(phi1h_arr - p4_thetaw)); Jsi_e = -HS(phi1h_arr - p4_thetaw)*w1h_arr*s1h_arr/p26_tau_si; J_h.vector()[:]= Jsi_e + Jso_e + Jfi_e + (Jfi_i + Jso_i)*phi1h_arr #********************************** # Solving PDE if (t >= est1_delay)*(t <= est1_delay + est1_duration): G = assemble(g1*v *ds(1) ) Gh = assemble(g1*vh*ds_h(1)) elif (t >= est2_delay)*(t <= est2_delay + est2_duration): G = assemble(g2*v *ds(4) ) Gh = assemble(g2*vh*ds_h(4)) else: G, Gh = 0, 0; F_k.vector()[:] = J.vector() b = M*phi1.vector() - dt*M*F_k.vector() + dt*G F_kh.vector()[:] = J_h.vector() bh = Mh*phi1h.vector() - dt*Mh*F_kh.vector() + dt*Gh start = time.time() solver.solve(A , phi.vector(), b) end = time.time(); time_solve = end - start start = time.time() solverh.solve(Ah, phih.vector(), bh) end = time.time(); time_solve_h = end - start phi1.assign(phi) phi1h.assign(phih) """ #********************************** # Evaluate L2-norm phi_hi = interpolate(phih, V) m2 = inner(phi-phi_hi, phi - phi_hi)*dx m3 = inner(phi, phi)*dx l2_norm_dif = assemble(m2) l2_norm = assemble(m3) error_rel = abs(l2_norm_dif/(l2_norm + (t <= est1_delay))) print "error = %g" % error_rel """ #********************************** # Export solutions to VTK (re-scaled to physiologycal values) if counter == 10: aux_out1.vector()[:] = 85.7*phi.vector() - 84 aux_out2.vector()[:] = 85.7*phih.vector() - 84 sol << aux_out1, t solh << aux_out2, t counter = 0 counter += 1 #error.write(str(t) + " " + str(error_rel) + "\n") benchmark.write(str(time_solve) + " " + str(time_solve_h) + "\n") t = t + dt
def compute(prms): ''' Pennes equattion solver author: Felipe Galarce email: [email protected] ''' from functions.inout import readmesh import os.path # Extract parameters mesh_file = './meshes/' + prms['io']['mesh'] + '.h5' results_dir = prms['io']['results'] dt = float(prms['num']['dt']) T = float(prms['num']['T']) # Parameters for Penne's equation rho = float(prms['phys']['rho']) rhob = float(prms['phys']['rhob']) c = float(prms['phys']['c']) cb = float(prms['phys']['cb']) k = float(prms['phys']['k']) Ta = float(prms['phys']['Ta']) Tc = float(prms['phys']['Tc']) wb = float(prms['phys']['wb']) Tf = float(prms['phys']['Tf']) hf = float(prms['phys']['hf']) # parameters for elasticity equations alpha = float(prms['phys']['alpha']) nu = float(prms['phys']['nu']) G = float(prms['phys']['G']) Qm_mode = prms['phys']['Qm_mode'] if Qm_mode == 'constant': Q_meta = float(33800) # Configuring form compiler # parameters["form_compiler"]["quadrature_degree"] = 6 parameters["form_compiler"]["optimize"] = True parameters["form_compiler"]["representation"] = 'quadrature' ## Read mesh, boundaries and subdomains, but first check if the mesh file exists if not os.path.isfile(mesh_file): import subprocess subprocess.call("cp ./meshes/" + prms['io']['mesh'] + ".geo ./", shell=True) subprocess.call("cp ./functions/xml2hdf5.py ./", shell=True) subprocess.call("gmsh -2 " + prms['io']['mesh'] + ".geo", shell=True) subprocess.call("dolfin-convert ./" + prms['io']['mesh'] + ".msh ./" + prms['io']['mesh'] + ".xml ", shell=True) subprocess.call("python xml2hdf5.py " + prms['io']['mesh'] + ".xml ", shell=True) subprocess.call("cp " + prms['io']['mesh'] + ".h5 ./meshes/", shell=True) subprocess.call("rm ./" + prms['io']['mesh'] + ".msh ./" + prms['io']['mesh'] + ".h5 ./" + prms['io']['mesh'] + ".xml ./" + prms['io']['mesh'] + "tissue_box_facet_region.xml " + prms['io']['mesh'] + "_physical_region.xml", shell=True) mesh, subdomains, boundaries = readmesh(mesh_file) # Characterize boundaries ds = Measure('ds', domain=mesh , subdomain_data=boundaries) # ============= HEAT EQUATION =============== # variational form V = FunctionSpace(mesh, "CG", 1) phi, v = TrialFunction(V), TestFunction(V) phi0, phit = Function(V), Function(V) a = rho*c/dt*inner(phi, v)*dx + k*inner(grad(phi), grad(v))*dx + cb*wb*inner(phi, v)*dx L = rho*c/dt*inner(phi0, v)*dx + inner(Constant(Q_meta), v)*dx + cb*wb*inner(Constant(Ta), v)*dx - inner(hf*phi0 - Constant(Tf), v)*ds(5) # point sources delta1 = PointSource(V, Point(0.009, 0.032, 0.04), float(prms['phys']['Pu'])) delta2 = PointSource(V, Point(0.009, 0.04, 0.028), float(prms['phys']['Pu'])) delta3 = PointSource(V, Point(0.009, 0.04, 0.028), float(prms['phys']['Pu'])) # Assemble LHS A = assemble(a) # boundary condition bc = DirichletBC(V, Expression(str(Tc)), boundaries, 1) # Configure solver and file to save solution solver = KrylovSolver('cg', 'amg') solver.parameters['report'] = False # solver.parameters['preconditioner']['structure'] = 'same' solver.parameters['nonzero_initial_guess'] = True phi_file = File(results_dir + "/temperature.pvd") # ============= ELASTICITY EQUATIONS =============== def update(u, u0, v0, a0, beta, gamma, dt): """Update fields at the end of each time step.""" # Get vectors (references) u_vec, u0_vec = u.vector(), u0.vector() v0_vec, a0_vec = v0.vector(), a0.vector() # Update acceleration and velocity # a = 1/(2*beta)*((u - u0 - v0*dt)/(0.5*dt*dt) - (1-2*beta)*a0) a_vec = (1.0/(2.0*beta))*( (u_vec - u0_vec - v0_vec*dt)/(0.5*dt*dt) - (1.0-2.0*beta)*a0_vec ) # v = dt * ((1-gamma)*a0 + gamma*a) + v0 v_vec = dt*((1.0-gamma)*a0_vec + gamma*a_vec) + v0_vec # Update (u0 <- u0) v0.vector()[:], a0.vector()[:] = v_vec, a_vec u0.vector()[:] = u.vector() # Newmark scheme parameters and function to compute acceleration beta = 0.25 gamma = 0.50 def ddot_u(u): return ((u - u0 - dt*v0)/(beta*dt*dt) - a0*(1 - 2*beta)/(2*beta)) #Function Spaces VV = VectorFunctionSpace(mesh, "Lagrange", 1) # displacement space uu, vv = TrialFunction(VV), TestFunction(VV) u0, v0, a0 = Function(VV), Function(VV), Function(VV) displacements = Function(VV) # symetric parts of test and trial functions eps_u, eps_v = sym(grad(uu)), sym(grad(vv)) # Lamme's Parameters lmbda, mu = 2.0*G*nu/(1 - 2*nu), G sig_u = lmbda*tr(eps_u)*Identity(2) + 2.*mu*eps_u # variational form F = inner(ddot_u(uu), vv)*dx + inner(sig_u, eps_v)*dx a_elasticity, L_elasticity = lhs(F), rhs(F) rank = mesh.mpi_comm().Get_rank() t = dt coupling_term = Function(VV) x_label = VV.sub(0).dofmap().dofs() y_label = VV.sub(1).dofmap().dofs() # # TODO: FIX BC # bc_disp = DirichletBC(VV, Expression(("0.0", "0.0")), boundaries, 1) print 'time [ms]: ' while t <= T + dt: if rank == 0: print '%g\t' % t, # --> SOLVING PENNE'S EQUATION # assemble RHS b = assemble(L) # if t == dt: # delta1.apply(b) # delta2.apply(b) # delta3.apply(b) # apply Dirichlet boundary conditions bc.apply(A, b) # solve linear system solver.solve(A, phit.vector(), b) # save solution to file phi_file << phi0 # --> SOLVING ELASTICITY EQUATIONS A_elasticity = assemble(a_elasticity); b_elasticity = assemble(L_elasticity) # coupling term coupling_term_arr = -2.0*G*alpha*(1 + nu)/(1 - 2*nu)*(phit.vector().array() - Tc) coupling_term.vector()[x_label] = coupling_term_arr coupling_term.vector()[y_label] = coupling_term_arr VF = assemble(inner(coupling_term, vv)*dx) b_elasticity = b_elasticity + VF # solve linear system bc_disp.apply(A_elasticity, b_elasticity) solve(A_elasticity, displacements.vector(), b_elasticity, 'gmres', 'ilu') # deform mesh accordingly to displacements field plot(phit) plot(displacements) plot(mesh) ALE.move(mesh, displacements) # interactive() update(displacements, u0, v0, a0, beta, gamma, dt) phi0.assign(phit) t += dt
def compute(prms): ''' Pennes equattion solver author: Felipe Galarce email: [email protected] ''' from functions.inout import readmesh import os.path import numpy as np import time import sys non_linear = 1 # Parameters for Penne's equation cb = float(prms['phys']['cb']) k = float(prms['phys']['k_tissue']) Tc = float(prms['phys']['Tc']) Tmax = prms['phys']['Tmax'] Tcr = prms['phys']['Tcr'] wb00 = prms['phys']['wb00'] wmax = prms['phys']['wmax'] Ta = prms['phys']['Ta'] Tc = 35 Ta = 37 Tsurr = Tc h_newton = 100 Rrad = 15 # TODO: fix this value def HS(x): # Heavy-Side function return (x > 0).astype(float) def Wb_(T): T_arr = T.vector().array(); wb.vector()[:] = wb00*HS(Tcr - T_arr) + (wmax + wb00)/2*HS(T_arr - Tmax) + wmax*(1 + ((wmax - wb00)/wb00)*((T_arr - Tcr)/(Tmax - Tcr)))*(1 - HS(T_arr - Tmax) - HS(Tcr - T_arr)) return wb def Qm_exp(T): T_arr = T.vector().array() exponente = (T_arr- 37)/10 dos = 2*np.ones(len(T_arr)) Qm.vector()[:] = 0.17*np.power(dos, exponente) return Qm if prms['options']['dim'] != 1: results_dir = prms['io']['results'] mesh_file = './meshes/' + prms['io']['mesh'] + '.h5' mesh, subdomains, boundaries = readmesh(mesh_file) # Characterize boundaries ds = Measure('ds', domain=mesh , subdomain_data=boundaries) else: mesh = IntervalMesh(100, 0, 0.05) V = FunctionSpace(mesh, "CG", 1) wb, Qm = Function(V), Function(V) du = TrialFunction(V) v = TestFunction(V) u_ = Function(V) # the most recently computed solution F = inner(k*grad(u_), grad(v))*dx \ - cb*inner(Wb_(u_)*u_, v)*dx \ + inner(Qm_exp(u_), v)*dx \ + cb*wb*inner(Ta, v)*dx \ + h_newton*inner(Constant(Tc - Ta), v)*dx #- 1.0/Rrad*inner(Constant(Tc - Tsurr), v)*dx J = derivative(F, u_, du) # Gateaux derivative in dir. of du if prms['options']['dim'] == 3: bc = DirichletBC(V, Tc, boundaries, 2) elif prms['options']['dim'] == 2: bc = DirichletBC(V, Tc, boundaries, 1) else: bc = DirichletBC(V, Tc, 'on_boundary') problem = NonlinearVariationalProblem(F, u_, bc, J) solver = NonlinearVariationalSolver(problem) prm = solver.parameters prm['newton_solver']['absolute_tolerance'] = 1E-8 prm['newton_solver']['relative_tolerance'] = 1E-7 prm['newton_solver']['maximum_iterations'] = 25 prm['newton_solver']['relaxation_parameter'] = 1.0 set_log_level(PROGRESS) solver.solve() out_file = File('./results/Skin2Blood.pvd') out_file << u_ plot(u_) interactive()