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()   
예제 #2
0
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
예제 #4
0
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()