def save_mesh_and_kappa_to_h5(mesh_to_h5,subdomains_to_h5,boundaries_to_h5,Field_calc_param): print("Number of mesh elements: ",mesh_to_h5.num_cells()) #due to the glitch with the ghost model and subdomains. Used only for c-c multicontact, so always with floating V0_r=FunctionSpace(mesh_to_h5,'DG',0) kappa_r=Function(V0_r) default_material=Field_calc_param.default_material [cond_GM, perm_GM]=DielectricProperties(3).get_dielectrics(Field_calc_param.frequenc) #3 for grey matter and so on (numeration as in voxel_data) [cond_WM, perm_WM]=DielectricProperties(2).get_dielectrics(Field_calc_param.frequenc) [cond_CSF, perm_CSF]=DielectricProperties(1).get_dielectrics(Field_calc_param.frequenc) [cond_default,perm_default]=DielectricProperties(default_material).get_dielectrics(Field_calc_param.frequenc) from GUI_inp_dict import d as d_encap [cond_encap, perm_encap]=DielectricProperties(d_encap['encap_tissue_type']).get_dielectrics(Field_calc_param.frequenc) cond_encap=cond_encap*d_encap['encap_scaling_cond'] perm_encap=perm_encap*d_encap['encap_scaling_perm'] k_val_r=[cond_default*0.001,cond_CSF*0.001,cond_WM*0.001,cond_GM*0.001,cond_encap*0.001,1000.0] help = np.asarray(subdomains_to_h5.array(), dtype=np.int32) kappa_r.vector()[:] = np.choose(help, k_val_r) hdf = HDF5File(mesh_to_h5.mpi_comm(), os.environ['PATIENTDIR']+'/Results_adaptive/Mesh_to_solve.h5', 'w') hdf.write(mesh_to_h5, "/mesh") hdf.write(subdomains_to_h5, "/subdomains") hdf.write(boundaries_to_h5, "/boundaries") hdf.write(kappa_r, "/kappa_r") file=File(os.environ['PATIENTDIR']+'/Results_adaptive/Last_subdomains_map.pvd') file<<subdomains_to_h5 file=File(os.environ['PATIENTDIR']+'/Results_adaptive/Last_conductivity_map.pvd') file<<kappa_r if Field_calc_param.EQS_mode == 'EQS': V0_i=FunctionSpace(mesh_to_h5,'DG',0) kappa_i=Function(V0_i) omega_eps0=2*np.pi*130.0*8.854e-12 #2*pi*f*eps0 k_val_i=[omega_eps0*perm_default*0.001,omega_eps0*perm_CSF*0.001,omega_eps0*perm_WM*0.001,omega_eps0*perm_GM*0.001,1*omega_eps0*perm_encap*0.001,1000000000*omega_eps0] help = np.asarray(subdomains_to_h5.array(), dtype=np.int32) kappa_i.vector()[:] = np.choose(help, k_val_i) hdf.write(kappa_i, "/kappa_i") file=File(os.environ['PATIENTDIR']+'/Results_adaptive/Last_permittivity_map.pvd') file<<kappa_i if Field_calc_param.anisotropy == 1: #we get unscaled tensors and scale them with conductivity here. This approach is needed only for MPI c00 = MeshFunction("double", mesh_to_h5, 3, 0.0) c01 = MeshFunction("double", mesh_to_h5, 3, 0.0) c02 = MeshFunction("double", mesh_to_h5, 3, 0.0) c11 = MeshFunction("double", mesh_to_h5, 3, 0.0) c12 = MeshFunction("double", mesh_to_h5, 3, 0.0) c22 = MeshFunction("double", mesh_to_h5, 3, 0.0) hdf2 = HDF5File(mesh_to_h5.mpi_comm(), os.environ['PATIENTDIR']+"/Results_adaptive/Tensors_to_solve_num_el_"+str(mesh_to_h5.num_cells())+".h5", "r") hdf2.read(c00, "/c00") hdf2.read(c01, "/c01") hdf2.read(c02, "/c02") hdf2.read(c11, "/c11") hdf2.read(c12, "/c12") hdf2.read(c22, "/c22") hdf2.close() cell_Anis = MeshFunction('bool',mesh_to_h5,3) cell_Anis.set_all(False) for cell in cells(mesh_to_h5): scale_cond=k_val_r[subdomains_to_h5[cell]] if c00[cell]!=1.0: cell_Anis[cell]=True c00[cell]=c00[cell]*scale_cond c01[cell]=c01[cell]*scale_cond c02[cell]=c02[cell]*scale_cond c11[cell]=c11[cell]*scale_cond c12[cell]=c12[cell]*scale_cond c22[cell]=c22[cell]*scale_cond file=File(os.environ['PATIENTDIR']+'/Tensors/c00_mapped.pvd') file<<c00,mesh_to_h5 file=File(os.environ['PATIENTDIR']+'/Tensors/c01_mapped.pvd') file<<c01,mesh_to_h5 file=File(os.environ['PATIENTDIR']+'/Tensors/c02_mapped.pvd') file<<c02,mesh_to_h5 file=File(os.environ['PATIENTDIR']+'/Tensors/c11_mapped.pvd') file<<c11,mesh_to_h5 file=File(os.environ['PATIENTDIR']+'/Tensors/c12_mapped.pvd') file<<c12,mesh_to_h5 file=File(os.environ['PATIENTDIR']+'/Tensors/c22_mapped.pvd') file<<c22,mesh_to_h5 file=File(os.environ['PATIENTDIR']+'/Tensors/Anis_cells.pvd') file<<cell_Anis,mesh_to_h5 hdf.write(c00, "/c00") hdf.write(c01, "/c01") hdf.write(c02, "/c02") hdf.write(c11, "/c11") hdf.write(c12, "/c12") hdf.write(c22, "/c22") hdf.close() return True
def get_field(mesh_sol, Domains, subdomains, boundaries_sol, Field_calc_param): set_log_active(False) #turns off debugging info print("_________________________") parameters['linear_algebra_backend'] = 'PETSc' [cond_GM, perm_GM] = DielectricProperties(3).get_dielectrics( Field_calc_param.frequenc ) #3 for grey matter and so on (numeration as in voxel_data) [cond_WM, perm_WM ] = DielectricProperties(2).get_dielectrics(Field_calc_param.frequenc) [cond_CSF, perm_CSF ] = DielectricProperties(1).get_dielectrics(Field_calc_param.frequenc) [cond_default, perm_default] = DielectricProperties( Field_calc_param.default_material).get_dielectrics( Field_calc_param.frequenc) from GUI_inp_dict import d as d_encap [cond_encap, perm_encap ] = DielectricProperties(d_encap['encap_tissue_type']).get_dielectrics( Field_calc_param.frequenc) cond_encap = cond_encap * d_encap['encap_scaling_cond'] perm_encap = perm_encap * d_encap['encap_scaling_perm'] if Field_calc_param.Solver_type == 'Default': Solver_type = choose_solver_for_me( Field_calc_param.EQS_mode, Domains.Float_contacts ) #choses solver basing on the Laplace formulation and whether the floating conductors are used else: Solver_type = Field_calc_param.Solver_type # just get the solver directly conductivities = [cond_default, cond_GM, cond_WM, cond_CSF, cond_encap] rel_permittivities = [perm_default, perm_GM, perm_WM, perm_CSF, perm_encap] # to get conductivity (and permittivity if EQS formulation) mapped accrodingly to the subdomains. k_val_r is just a list of conductivities (S/mm!) in a specific order to scale the cond. tensor from FEM_in_spectrum import get_dielectric_properties_from_subdomains kappa, k_val_r = get_dielectric_properties_from_subdomains( mesh_sol, subdomains, Field_calc_param.EQS_mode, Domains.Float_contacts, conductivities, rel_permittivities, Field_calc_param.frequenc) file = File('/opt/Patient/Results_adaptive/Last_subdomains_map.pvd') file << subdomains file = File('/opt/Patient/Results_adaptive/Last_conductivity_map.pvd') file << kappa[0] if Field_calc_param.EQS_mode == 'EQS': file = File('/opt/Patient/Results_adaptive/Last_permittivity_map.pvd') file << kappa[1] if Field_calc_param.anisotropy == 1: # order xx,xy,xz,yy,yz,zz c00 = MeshFunction("double", mesh_sol, 3, 0.0) c01 = MeshFunction("double", mesh_sol, 3, 0.0) c02 = MeshFunction("double", mesh_sol, 3, 0.0) c11 = MeshFunction("double", mesh_sol, 3, 0.0) c12 = MeshFunction("double", mesh_sol, 3, 0.0) c22 = MeshFunction("double", mesh_sol, 3, 0.0) # load the diffusion tensor (should be normalized beforehand) hdf = HDF5File( mesh_sol.mpi_comm(), "/opt/Patient/Results_adaptive/Tensors_to_solve_num_el_" + str(mesh_sol.num_cells()) + ".h5", "r") hdf.read(c00, "/c00") hdf.read(c01, "/c01") hdf.read(c02, "/c02") hdf.read(c11, "/c11") hdf.read(c12, "/c12") hdf.read(c22, "/c22") hdf.close() unscaled_tensor = [c00, c01, c02, c11, c12, c22] # to get tensor scaled by the conductivity map (twice send Field_calc_param.frequenc to always get unscaled ellipsoid tensor for visualization) from FEM_in_spectrum import get_scaled_cond_tensor Cond_tensor = get_scaled_cond_tensor(mesh_sol, subdomains, Field_calc_param.frequenc, Field_calc_param.frequenc, unscaled_tensor, k_val_r, plot_tensors=True) else: Cond_tensor = False #just to initialize #In case of current-controlled stimulation, Dirichlet_bc or the whole potential distribution will be scaled afterwards (due to the system's linearity) from FEM_in_spectrum import get_solution_space_and_Dirichlet_BC V_space, Dirichlet_bc, ground_index, facets = get_solution_space_and_Dirichlet_BC( Field_calc_param.external_grounding, Field_calc_param.c_c, mesh_sol, subdomains, boundaries_sol, Field_calc_param.element_order, Field_calc_param.EQS_mode, Domains.Contacts, Domains.fi) #ground index refers to the ground in .med/.msh file print("dofs: ", (max(V_space.dofmap().dofs()) + 1)) print("N of elements: ", mesh_sol.num_cells()) #facets = MeshFunction('size_t',mesh_sol,2) #facets.set_all(0) if Field_calc_param.external_grounding == False: # otherwise we have it already from get_solution_space_and_Dirichlet_BC() facets.array()[boundaries_sol.array() == Domains.Contacts[ground_index]] = 1 dsS = Measure("ds", domain=mesh_sol, subdomain_data=facets) Ground_surface_size = assemble(1.0 * dsS(1)) dx = Measure("dx", domain=mesh_sol) # to solve the Laplace equation div(kappa*grad(phi))=0 (variational form: a(u,v)=L(v)) start_math = tm.time() from FEM_in_spectrum import define_variational_form_and_solve phi_sol = define_variational_form_and_solve(V_space, Dirichlet_bc, kappa, Field_calc_param.EQS_mode, Cond_tensor, Solver_type) minutes = int((tm.time() - start_math) / 60) secnds = int(tm.time() - start_math) - minutes * 60 print("--- assembled and solved in ", minutes, " min ", secnds, " s ---") if Field_calc_param.EQS_mode == 'EQS': (phi_r_sol, phi_i_sol) = phi_sol.split(deepcopy=True) else: phi_r_sol = phi_sol phi_i_sol = Function(V_space) phi_i_sol.vector()[:] = 0.0 # get current flowing through the grounded contact and the electric field in the whole domain from FEM_in_spectrum import get_current J_ground, E_field, E_field_im = get_current(mesh_sol, facets, boundaries_sol, Field_calc_param.element_order, Field_calc_param.EQS_mode, Domains.Contacts, kappa, Cond_tensor, phi_r_sol, phi_i_sol, ground_index, get_E_field=True) #print("J_ground_unscaled: ",J_ground) # If EQS, J_ground is a complex number. If QS, E_field_im is a null function # to get current density function which is required for mesh refinement when checking current convergence j_dens_real, j_dens_im = get_current_density( mesh_sol, Field_calc_param.element_order, Field_calc_param.EQS_mode, kappa, Cond_tensor, E_field, E_field_im) # If QS, j_dens_im is null function # will be used for mesh refinement j_dens_real_unscaled = j_dens_real.copy(deepcopy=True) j_dens_im_unscaled = j_dens_im.copy(deepcopy=True) # null function if QS import copy J_real_unscaled = copy.deepcopy(np.real(J_ground)) J_im_unscaled = copy.deepcopy(np.imag(J_ground)) # 0 if QS # to project the E-field magnitude if Field_calc_param.element_order > 1: V_normE = FunctionSpace(mesh_sol, "CG", Field_calc_param.element_order - 1) else: V_normE = FunctionSpace(mesh_sol, "CG", Field_calc_param.element_order) #V_across=max(Domains.fi[:], key=abs) #actually, not across, but against ground!!! if Field_calc_param.external_grounding == True and ( Field_calc_param.c_c == 1 or len(Domains.fi) == 1): V_max = max(Domains.fi[:], key=abs) V_min = 0.0 elif -1 * Domains.fi[0] == Domains.fi[ 1]: # V_across is needed only for 2 active contact systems V_min = -1 * abs(Domains.fi[0]) V_max = abs(Domains.fi[0]) else: V_min = min(Domains.fi[:], key=abs) V_max = max(Domains.fi[:], key=abs) V_across = V_max - V_min # this can be negative Vertices_get = read_csv( '/opt/Patient/Neuron_model_arrays/Vert_of_Neural_model_NEURON.csv', delimiter=' ', header=None) Vertices_array = Vertices_get.values Phi_ROI = np.zeros((Vertices_array.shape[0], 4), float) for inx in range(Vertices_array.shape[0]): pnt = Point(Vertices_array[inx, 0], Vertices_array[inx, 1], Vertices_array[inx, 2]) Phi_ROI[inx, 0] = Vertices_array[inx, 0] Phi_ROI[inx, 1] = Vertices_array[inx, 1] Phi_ROI[inx, 2] = Vertices_array[inx, 2] if Field_calc_param.c_c == 1: phi_r_sol_scaled_on_point = V_across * np.real( (phi_r_sol(pnt) + 1j * phi_i_sol(pnt)) / J_ground) phi_i_sol_scaled_on_point = V_across * np.imag( (phi_r_sol(pnt) + 1j * phi_i_sol(pnt)) / J_ground) Phi_ROI[inx, 3] = np.sqrt( phi_r_sol_scaled_on_point * phi_r_sol_scaled_on_point + phi_i_sol_scaled_on_point * phi_i_sol_scaled_on_point) else: Phi_ROI[inx, 3] = np.sqrt( phi_r_sol(pnt) * phi_r_sol(pnt) + phi_i_sol(pnt) * phi_i_sol(pnt)) np.savetxt('/opt/Patient/Results_adaptive/Phi_' + str(Field_calc_param.frequenc) + '.csv', Phi_ROI, delimiter=" ") # this is amplitude, actually # #Probe_of_potential # probe_z=np.zeros((100,4),float) # for inx in range(100): # pnt=Point(75.5,78.5,27.865+inx/10.0) # probe_z[inx,0]=75.5 # probe_z[inx,1]=78.5 # probe_z[inx,2]=27.865+inx/10.0 # if Field_calc_param.c_c==1: # phi_r_sol_scaled_on_point=V_across*np.real((phi_r_sol(pnt)+1j*phi_i_sol(pnt))/(J_real_unscaled+1j*J_im_unscaled)) # phi_i_sol_scaled_on_point=V_across*np.imag((phi_r_sol(pnt)+1j*phi_i_sol(pnt))/(J_real_unscaled+1j*J_im_unscaled)) # probe_z[inx,3]=np.sqrt(phi_r_sol_scaled_on_point*phi_r_sol_scaled_on_point+phi_i_sol_scaled_on_point*phi_i_sol_scaled_on_point) # else: # probe_z[inx,3]=np.sqrt(phi_r_sol(pnt)*phi_r_sol(pnt)+phi_i_sol(pnt)*phi_i_sol(pnt)) # np.savetxt('Results_adaptive/Phi_Zprobe'+str(Field_calc_param.frequenc)+'.csv', probe_z, delimiter=" ") #print("Tissue impedance: ", Z_tis) #=============================================================================# if Field_calc_param.c_c == 1 or Field_calc_param.CPE == 1: Z_tissue = V_across / J_ground # Tissue impedance print("Tissue impedance: ", Z_tissue) if Field_calc_param.CPE == 1: if len(Domains.fi) > 2: print( "Currently, CPE can be used only for simulations with two contacts. Please, assign the rest to 'None'" ) raise SystemExit from GUI_inp_dict import d as d_cpe CPE_param = [ d_cpe["K_A"], d_cpe["beta"], d_cpe["K_A_ground"], d_cpe["beta_ground"] ] from FEM_in_spectrum import get_CPE_corrected_Dirichlet_BC Dirichlet_bc_with_CPE, total_impedance = get_CPE_corrected_Dirichlet_BC( Field_calc_param.external_grounding, facets, boundaries_sol, CPE_param, Field_calc_param.EQS_mode, Field_calc_param.frequenc, Field_calc_param.frequenc, Domains.Contacts, Domains.fi, V_across, Z_tissue, V_space) print( "Solving for an adjusted potential on contacts to account for CPE" ) start_math = tm.time() # to solve the Laplace equation for the adjusted Dirichlet phi_sol_CPE = define_variational_form_and_solve( V_space, Dirichlet_bc_with_CPE, kappa, Field_calc_param.EQS_mode, Cond_tensor, Solver_type) minutes = int((tm.time() - start_math) / 60) secnds = int(tm.time() - start_math) - minutes * 60 print("--- assembled and solved in ", minutes, " min ", secnds, " s ") if Field_calc_param.EQS_mode == 'EQS': (phi_r_CPE, phi_i_CPE) = phi_sol_CPE.split(deepcopy=True) else: phi_r_CPE = phi_sol_CPE phi_i_CPE = Function(V_space) phi_i_CPE.vector()[:] = 0.0 # get current flowing through the grounded contact and the electric field in the whole domain J_ground_CPE, E_field_CPE, E_field_im_CPE = get_current( mesh_sol, facets, boundaries_sol, Field_calc_param.element_order, Field_calc_param.EQS_mode, Domains.Contacts, kappa, Cond_tensor, phi_r_CPE, phi_i_CPE, ground_index, get_E_field=True) # If EQS, J_ground is a complex number. If QS, E_field_CPE is a null function # to get current density function which is required for mesh refinement when checking current convergence j_dens_real_CPE, j_dens_im_CPE = get_current_density( mesh_sol, Field_calc_param.element_order, Field_calc_param.EQS_mode, kappa, Cond_tensor, E_field_CPE, E_field_im_CPE) # If QS, j_dens_im is null function # will be used for mesh refinement j_dens_real_unscaled = j_dens_real_CPE.copy(deepcopy=True) j_dens_im_unscaled = j_dens_im_CPE.copy(deepcopy=True) J_real_unscaled = copy.deepcopy(np.real(J_ground)) J_im_unscaled = copy.deepcopy(np.imag(J_ground)) E_norm = project(sqrt( inner(E_field_CPE, E_field_CPE) + inner(E_field_im_CPE, E_field_im_CPE)), V_normE, solver_type="cg", preconditioner_type="amg") max_E = E_norm.vector().max() file = File('/opt/Patient/Results_adaptive/E_ampl_' + str(Field_calc_param.EQS_mode) + '.pvd') file << E_norm, mesh_sol file = File('/opt/Patient/Results_adaptive/Last_Phi_r_field_' + str(Field_calc_param.EQS_mode) + '.pvd') file << phi_r_CPE, mesh_sol if Field_calc_param.EQS_mode == 'EQS': file = File( '/opt/Patient/Results_adaptive/Last_Phi_im_field_' + str(Field_calc_param.EQS_mode) + '.pvd') file << phi_i_CPE, mesh_sol return phi_r_CPE, phi_i_CPE, E_field_CPE, E_field_im_CPE, max_E, J_real_unscaled, J_im_unscaled, j_dens_real_unscaled, j_dens_im_unscaled if Field_calc_param.c_c == 1: if Field_calc_param.EQS_mode == 'EQS': # For EQS, we need to scale the potential on boundaries (because the error is absolute) and recompute field, etc. Maybe we can scale them also directly? Dirichlet_bc_scaled = [] for bc_i in range( len(Domains.Contacts) ): #CPE estimation is valid only for one activa and one ground contact configuration if Field_calc_param.EQS_mode == 'EQS': if Domains.fi[bc_i] != 0.0: Active_with_CC = V_across * V_across / J_ground #(impedance * current through the contact (V_across coincides with the assigned current magnitude)) Dirichlet_bc_scaled.append( DirichletBC(V_space.sub(0), np.real(Active_with_CC), boundaries_sol, Domains.Contacts[bc_i])) Dirichlet_bc_scaled.append( DirichletBC(V_space.sub(1), np.imag(Active_with_CC), boundaries_sol, Domains.Contacts[bc_i])) else: Dirichlet_bc_scaled.append( DirichletBC(V_space.sub(0), Constant(0.0), boundaries_sol, Domains.Contacts[bc_i])) Dirichlet_bc_scaled.append( DirichletBC(V_space.sub(1), Constant(0.0), boundaries_sol, Domains.Contacts[bc_i])) if Field_calc_param.external_grounding == True: if Field_calc_param.EQS_mode == 'EQS': Dirichlet_bc_scaled.append( DirichletBC(V_space.sub(0), 0.0, facets, 1)) Dirichlet_bc_scaled.append( DirichletBC(V_space.sub(1), 0.0, facets, 1)) else: Dirichlet_bc_scaled.append( DirichletBC(V_space, 0.0, facets, 1)) print( "Solving for a scaled potential on contacts (to match the desired current)" ) start_math = tm.time() # to solve the Laplace equation for the adjusted Dirichlet phi_sol_scaled = define_variational_form_and_solve( V_space, Dirichlet_bc_scaled, kappa, Field_calc_param.EQS_mode, Cond_tensor, Solver_type) minutes = int((tm.time() - start_math) / 60) secnds = int(tm.time() - start_math) - minutes * 60 print("--- assembled and solved in ", minutes, " min ", secnds, " s ---") (phi_r_sol_scaled, phi_i_sol_scaled) = phi_sol_scaled.split(deepcopy=True) # get current flowing through the grounded contact and the electric field in the whole domain J_ground_scaled, E_field_scaled, E_field_im_scaled = get_current( mesh_sol, facets, boundaries_sol, Field_calc_param.element_order, Field_calc_param.EQS_mode, Domains.Contacts, kappa, Cond_tensor, phi_r_sol_scaled, phi_i_sol_scaled, ground_index, get_E_field=True) # If EQS, J_ground is a complex number. If QS, E_field_im is 0 else: # here we can simply scale the potential in the domain and recompute the E-field phi_i_sol_scaled = Function(V_space) phi_i_sol_scaled.vector()[:] = 0.0 phi_r_sol_scaled = Function(V_space) phi_r_sol_scaled.vector( )[:] = V_across * phi_r_sol.vector()[:] / J_ground J_ground_scaled, E_field_scaled, E_field_im_scaled = get_current( mesh_sol, facets, boundaries_sol, Field_calc_param.element_order, Field_calc_param.EQS_mode, Domains.Contacts, kappa, Cond_tensor, phi_r_sol_scaled, phi_i_sol_scaled, ground_index, get_E_field=True) #E_field_im_scale is a null function E_norm = project(sqrt( inner(E_field_scaled, E_field_scaled) + inner(E_field_im_scaled, E_field_im_scaled)), V_normE, solver_type="cg", preconditioner_type="amg") max_E = E_norm.vector().max() file = File('/opt/Patient/Results_adaptive/E_ampl_' + str(Field_calc_param.EQS_mode) + '.pvd') file << E_norm, mesh_sol file = File('/opt/Patient/Results_adaptive/Last_Phi_r_field_' + str(Field_calc_param.EQS_mode) + '.pvd') file << phi_r_sol_scaled, mesh_sol if Field_calc_param.EQS_mode == 'EQS': file = File( '/opt/Patient/Results_adaptive/Last_Phi_im_field_' + str(Field_calc_param.EQS_mode) + '.pvd') file << phi_i_sol_scaled, mesh_sol return phi_r_sol_scaled, phi_i_sol_scaled, E_field_scaled, E_field_im_scaled, max_E, J_real_unscaled, J_im_unscaled, j_dens_real_unscaled, j_dens_im_unscaled else: E_norm = project( sqrt(inner(E_field, E_field) + inner(E_field_im, E_field_im)), V_normE, solver_type="cg", preconditioner_type="amg") max_E = E_norm.vector().max() file = File('/opt/Patient/Results_adaptive/E_ampl_' + str(Field_calc_param.EQS_mode) + '.pvd') file << E_norm, mesh_sol file = File('/opt/Patient/Results_adaptive/Last_Phi_r_field_' + str(Field_calc_param.EQS_mode) + '.pvd') file << phi_r_sol, mesh_sol if Field_calc_param.EQS_mode == 'EQS': file = File('/opt/Patient/Results_adaptive/Last_Phi_im_field_' + str(Field_calc_param.EQS_mode) + '.pvd') file << phi_i_sol, mesh_sol return phi_r_sol, phi_i_sol, E_field, E_field_im, max_E, J_real_unscaled, J_im_unscaled, j_dens_real_unscaled, j_dens_im_unscaled
def get_field_with_scaled_BC(mesh_sol, Domains, Phi_scaled, subdomains, boundaries_sol, default_material, element_order, Laplace_mode, anisotropy, frequenc, Solver_type, calc_with_MPI=False, kappa=False): set_log_active(False) #turns off debugging info parameters['linear_algebra_backend'] = 'PETSc' if calc_with_MPI == False or MPI.comm_world.rank == 1: print("Calculating field with scaled voltage on contacts") if calc_with_MPI == False: [cond_GM, perm_GM] = DielectricProperties(3).get_dielectrics( frequenc ) #3 for grey matter and so on (numeration as in voxel_data) [cond_WM, perm_WM] = DielectricProperties(2).get_dielectrics(frequenc) [cond_CSF, perm_CSF] = DielectricProperties(1).get_dielectrics(frequenc) [cond_default, perm_default ] = DielectricProperties(default_material).get_dielectrics(frequenc) from GUI_inp_dict import d as d_encap [cond_encap, perm_encap] = DielectricProperties( d_encap['encap_tissue_type']).get_dielectrics(frequenc) cond_encap = cond_encap * d_encap['encap_scaling_cond'] perm_encap = perm_encap * d_encap['encap_scaling_perm'] conductivities = [cond_default, cond_GM, cond_WM, cond_CSF, cond_encap] rel_permittivities = [ perm_default, perm_GM, perm_WM, perm_CSF, perm_encap ] # to get conductivity (and permittivity if EQS formulation) mapped accrodingly to the subdomains. k_val_r is just a list of conductivities (S/mm!) in a specific order to scale the cond. tensor from FEM_in_spectrum import get_dielectric_properties_from_subdomains kappa, k_val_r = get_dielectric_properties_from_subdomains( mesh_sol, subdomains, Laplace_mode, Domains.Float_contacts, conductivities, rel_permittivities, frequenc) file = File('Results_adaptive/Last_subdomains_map.pvd') file << subdomains file = File('Results_adaptive/Last_conductivity_map.pvd') file << kappa[0] if Laplace_mode == 'EQS': file = File('Results_adaptive/Last_permittivity_map.pvd') file << kappa[1] if anisotropy == 1: # order xx,xy,xz,yy,yz,zz c00 = MeshFunction("double", mesh_sol, 3, 0.0) c01 = MeshFunction("double", mesh_sol, 3, 0.0) c02 = MeshFunction("double", mesh_sol, 3, 0.0) c11 = MeshFunction("double", mesh_sol, 3, 0.0) c12 = MeshFunction("double", mesh_sol, 3, 0.0) c22 = MeshFunction("double", mesh_sol, 3, 0.0) if calc_with_MPI == True: #load predefined Tensor Cond_tensor = load_scaled_cond_tensor(c00, c01, c02, c11, c12, c22, mesh_sol) else: # load the unscaled diffusion tensor (should be normalized beforehand) hdf = HDF5File( mesh_sol.mpi_comm(), "Results_adaptive/Tensors_to_solve_num_el_" + str(mesh_sol.num_cells()) + ".h5", "r") hdf.read(c00, "/c00") hdf.read(c01, "/c01") hdf.read(c02, "/c02") hdf.read(c11, "/c11") hdf.read(c12, "/c12") hdf.read(c22, "/c22") hdf.close() unscaled_tensor = [c00, c01, c02, c11, c12, c22] # to get tensor scaled by the conductivity map (twice send frequenc to always get unscaled ellipsoid tensor for visualization) from FEM_in_spectrum import get_scaled_cond_tensor Cond_tensor = get_scaled_cond_tensor(mesh_sol, subdomains, frequenc, frequenc, unscaled_tensor, k_val_r, plot_tensors=True) else: Cond_tensor = False #just to initialize from FEM_in_spectrum import get_solution_space_and_Dirichlet_BC V_space = get_solution_space_and_Dirichlet_BC(1, mesh_sol, boundaries_sol, element_order, Laplace_mode, Domains.Contacts, Phi_scaled, only_space=True) Dirichlet_bc_scaled = [] if calc_with_MPI == False or MPI.comm_world.rank == 1: print("Scaled complex potential on contacts: ", Phi_scaled[:]) for bc_i in range(len(Domains.Contacts)): if Laplace_mode == 'EQS': Dirichlet_bc_scaled.append( DirichletBC(V_space.sub(0), np.real(Phi_scaled[bc_i]), boundaries_sol, Domains.Contacts[bc_i])) Dirichlet_bc_scaled.append( DirichletBC(V_space.sub(1), np.imag(Phi_scaled[bc_i]), boundaries_sol, Domains.Contacts[bc_i])) else: Dirichlet_bc_scaled.append( DirichletBC(V_space, Phi_scaled[bc_i], boundaries_sol, Domains.Contacts[bc_i])) #facets.array()[boundaries_sol.array()==Domains.Contacts[bc_i]]=bc_i+1 # to solve the Laplace equation div(kappa*grad(phi))=0 (variational form: a(u,v)=L(v)) from FEM_in_spectrum import define_variational_form_and_solve phi_sol = define_variational_form_and_solve(V_space, Dirichlet_bc_scaled, kappa, Laplace_mode, Cond_tensor, Solver_type) if Laplace_mode == 'EQS': (phi_r_sol, phi_i_sol) = phi_sol.split(deepcopy=True) else: phi_r_sol = phi_sol phi_i_sol = Function(V_space) phi_i_sol.vector()[:] = 0.0 # to get manual projections for the E-field from FEM_in_spectrum_multicontact import get_E_field E_field, E_field_im = get_E_field(mesh_sol, element_order, Laplace_mode, phi_r_sol, phi_i_sol) #if QS, E_field_im is a null function # to get current density function which is required for mesh refinement when checking current convergence from Math_module_hybrid import get_current_density j_dens_real, j_dens_im = get_current_density(mesh_sol, element_order, Laplace_mode, kappa, Cond_tensor, E_field, E_field_im) # If QS, j_dens_im is null function # to project the E-field magnitude if element_order > 1: V_normE = FunctionSpace(mesh_sol, "CG", element_order - 1) else: V_normE = FunctionSpace(mesh_sol, "CG", element_order) # to get current on the active contacts (inlcuding the ground) from FEM_in_spectrum_multicontact import get_current_on_multiple_contacts J_r_contacts, J_im_contacts = get_current_on_multiple_contacts( mesh_sol, boundaries_sol, Laplace_mode, Domains.Contacts, Phi_scaled, E_field, E_field_im, kappa, Cond_tensor) # J_currents_imag is a zero array if 'QS' mode if calc_with_MPI == False: Vertices_get = read_csv( 'Neuron_model_arrays/Vert_of_Neural_model_NEURON.csv', delimiter=' ', header=None) Vertices_array = Vertices_get.values Phi_ROI = np.zeros((Vertices_array.shape[0], 4), float) for inx in range(Vertices_array.shape[0]): pnt = Point(Vertices_array[inx, 0], Vertices_array[inx, 1], Vertices_array[inx, 2]) Phi_ROI[inx, 0] = Vertices_array[inx, 0] Phi_ROI[inx, 1] = Vertices_array[inx, 1] Phi_ROI[inx, 2] = Vertices_array[inx, 2] Phi_ROI[inx, 3] = np.sqrt( phi_r_sol(pnt) * phi_r_sol(pnt) + phi_i_sol(pnt) * phi_i_sol(pnt)) np.savetxt('Results_adaptive/Phi_' + str(frequenc) + '.csv', Phi_ROI, delimiter=" ") # this is amplitude, actually Quasi_imp_real = np.zeros(len(Domains.Contacts), float) #not really, but gives an idea Quasi_imp_im = np.zeros(len(Domains.Contacts), float) #not really, but gives an idea for bc_i in range(len(Domains.Contacts)): if calc_with_MPI == False or MPI.comm_world.rank == 1: print("J on contact ", Domains.Active_on_lead[bc_i], ": ", J_r_contacts[bc_i] + 1j * J_im_contacts[bc_i], "A") Quasi_imp_real[bc_i] = np.real( Phi_scaled[bc_i] / (J_r_contacts[bc_i] + 1j * J_im_contacts[bc_i])) if Laplace_mode == 'EQS': Quasi_imp_im[bc_i] = np.imag( Phi_scaled[bc_i] / (J_r_contacts[bc_i] + 1j * J_im_contacts[bc_i])) J_r_max = J_r_contacts.max( ) # we need it to filter out contacts with very small currents (they have very high quasi-impedance) ind_high_current = [] for bc_i in range(len(Domains.Contacts)): if J_r_contacts[bc_i] >= 0.1 * J_r_max: ind_high_current.append(bc_i) Quasi_imp_real_total = np.sum(abs(Quasi_imp_real[ind_high_current])) Quasi_imp_im_total = np.sum(abs(Quasi_imp_im[ind_high_current])) if calc_with_MPI == True: J_Vector = Vector(MPI.comm_self, 2) J_Vector.set_local( np.array([Quasi_imp_real_total, Quasi_imp_im_total], dtype=np.float64)) Hdf = HDF5File( mesh_sol.mpi_comm(), "Results_adaptive/Solution_" + str(np.round(frequenc, 6)) + ".h5", "w") Hdf.write(mesh_sol, "mesh_sol") Hdf.write(phi_sol, "solution_phi_full") Hdf.write(E_field, "solution_E_field") Hdf.write(E_field_im, "solution_E_field_im") Hdf.write(j_dens_real, "solution_j_real") Hdf.write(j_dens_im, "solution_j_im") Hdf.write(J_Vector, "/J_Vector") Hdf.close() return True else: print("Quasi_impedance (for current check):", sqrt(Quasi_imp_real_total**2 + Quasi_imp_im_total**2)) E_norm = project( sqrt(inner(E_field, E_field) + inner(E_field_im, E_field_im)), V_normE, solver_type="cg", preconditioner_type="amg") max_E = E_norm.vector().max() if calc_with_MPI == False or MPI.comm_world.rank == 1: file = File('Results_adaptive/E_ampl_' + str(Laplace_mode) + '.pvd') file << E_norm, mesh_sol file = File('Results_adaptive/Last_Phi_r_field_' + str(Laplace_mode) + '.pvd') file << phi_r_sol, mesh_sol if Laplace_mode == 'EQS': file = File('Results_adaptive/Last_Phi_im_field_' + str(Laplace_mode) + '.pvd') file << phi_i_sol, mesh_sol return (phi_r_sol, phi_i_sol, E_field, E_field_im, max_E, Quasi_imp_real_total, Quasi_imp_im_total, j_dens_real, j_dens_im)
def calculate_in_parallel(d, freq_list, Domains, MRI_param, DTI_param, anisotropy, number_of_points, cc_multicontact): start_paral = tm.time() Field_on_VTA = 0 #temp solution if d["Full_Field_IFFT"] == 1: Field_on_VTA = 1 d["Full_Field_IFFT"] = 0 #load adapted mesh mesh = Mesh(os.environ['PATIENTDIR'] + '/Results_adaptive/mesh_adapt.xml.gz') boundaries = MeshFunction( 'size_t', mesh, os.environ['PATIENTDIR'] + '/Results_adaptive/boundaries_adapt.xml') subdomains_assigned = MeshFunction( 'size_t', mesh, os.environ['PATIENTDIR'] + '/Results_adaptive/subdomains_assigned_adapt.xml') #load the neuron array Vertices_get = read_csv( os.environ['PATIENTDIR'] + '/Neuron_model_arrays/Vert_of_Neural_model_NEURON.csv', delimiter=' ', header=None) Vertices = Vertices_get.values #load CPE parameters if necessary CPE_param = [] # just initialization if d["CPE_activ"] == 1: CPE_param = [d["K_A"], d["beta"], d["K_A_ground"], d["beta_ground"]] #load unscaled tensors if DTI data are provided if anisotropy == 1: from Tissue_marking_new import get_cellmap_tensors subdomains = get_cellmap_tensors( mesh, subdomains_assigned, Domains, MRI_param, DTI_param, d["default_material"]) #mapping of tissue onto the mesh #initiating with isotropic tensor c00 = MeshFunction("double", mesh, 3, 1.0) c01 = MeshFunction("double", mesh, 3, 0.0) c02 = MeshFunction("double", mesh, 3, 0.0) c11 = MeshFunction("double", mesh, 3, 1.0) c12 = MeshFunction("double", mesh, 3, 0.0) c22 = MeshFunction("double", mesh, 3, 1.0) hdf = HDF5File( mesh.mpi_comm(), os.environ['PATIENTDIR'] + "/Results_adaptive/Tensors_to_solve_num_el_" + str(mesh.num_cells()) + ".h5", "r") hdf.read(c00, "/c00") hdf.read(c01, "/c01") hdf.read(c02, "/c02") hdf.read(c11, "/c11") hdf.read(c12, "/c12") hdf.read(c22, "/c22") hdf.close() DTI_tensor = [c00, c01, c02, c11, c12, c22] else: from Tissue_marking_new import get_cellmap subdomains = get_cellmap( mesh, subdomains_assigned, Domains, MRI_param, d["default_material"]) #mapping of tissue onto the mesh DTI_tensor = [0, 0, 0, 0, 0, 0] #initiating print( "Subdomains file for parallel is saved in Field_solutions/parallel_Subdomains.pvd" ) file = File(os.environ['PATIENTDIR'] + '/Field_solutions/parallel_Subdomains.pvd') file << subdomains, mesh # choose solver if d['Solver_Type'] == 'Default': from Math_module_hybrid import choose_solver_for_me Solver_type = choose_solver_for_me( d["EQS_core"], Domains.Float_contacts ) #choses solver basing on the Laplace formulation and whether the floating conductors are used else: Solver_type = d['Solver_Type'] # just get the solver directly print("Solver: ", Solver_type) #with open(os.devnull, 'w') as FNULL: subprocess.call('python Paraview_adapted.py', shell=True, stdout=FNULL, stderr=subprocess.STDOUT) i = 0 #frequency index in the frequency list of the signal spectrum complete_solution = [] # this snippet will check at which frequency the FFEM computations were interrupted if d["Parallel_comp_interrupted"] == 1: pack_to_start_after = np.genfromtxt( os.environ['PATIENTDIR'] + '/Field_solutions/last_completed_pack.csv', delimiter=' ') if pack_to_start_after.size == 1: rslt = np.where(freq_list == pack_to_start_after) i = rslt[0][0] + 1 elif pack_to_start_after[-1] == freq_list[-1]: i = freq_list.shape[0] print( "All computations in frequency spectrum were already conducted" ) else: rslt = np.where(freq_list == pack_to_start_after[-1]) i = rslt[0][0] + 1 #FFEM calculations are conducted in parallel while i < freq_list.shape[0]: proc = [] j = 0 #counter for processes output = mp.Queue() freq_pack = [] while j < d["number_of_processors"] and i < freq_list.shape[0]: sine_freq = freq_list[i] freq_pack.append(sine_freq) i = i + 1 [cond_GM, perm_GM] = DielectricProperties(3).get_dielectrics( sine_freq) #1 for grey matter and so on [cond_WM, perm_WM] = DielectricProperties(2).get_dielectrics(sine_freq) [cond_CSF, perm_CSF] = DielectricProperties(1).get_dielectrics(sine_freq) [cond_default, perm_default] = DielectricProperties( d["default_material"]).get_dielectrics(sine_freq) [cond_encap, perm_encap] = DielectricProperties( d["encap_tissue_type"]).get_dielectrics(sine_freq) cond_encap = cond_encap * d["encap_scaling_cond"] perm_encap = perm_encap * d["encap_scaling_perm"] cond_vector = [ cond_default, cond_GM, cond_WM, cond_CSF, cond_encap ] perm_vector = [ perm_default, perm_GM, perm_WM, perm_CSF, perm_encap ] Sim_setup = Simulation_setup( sine_freq, d["freq"], mesh, boundaries, subdomains, cond_vector, perm_vector, d["el_order"], anisotropy, d["current_control"], DTI_tensor, d["CPE_activ"], CPE_param, d["EQS_core"], d["external_grounding"]) import Contact_ground_calc processes = mp.Process( target=Contact_ground_calc.compute_fields_from_unit_currents, args=(Sim_setup, Solver_type, Vertices, Domains, j, Field_on_VTA, output)) # if cc_multicontact==True: # import FEM_in_spectrum_multicontact # processes=mp.Process(target=FEM_in_spectrum_multicontact.solve_Laplace_multicontact,args=(Sim_setup,Solver_type,Vertices,Domains,j,Field_on_VTA,output)) # else: # import FEM_in_spectrum # processes=mp.Process(target=FEM_in_spectrum.solve_Laplace,args=(Sim_setup,Solver_type,Vertices,Domains,j,Field_on_VTA,output)) proc.append(processes) j = j + 1 for p in proc: p.start() for p in proc: p.join() last_completed_pack = np.asarray(freq_pack) np.savetxt(os.environ['PATIENTDIR'] + '/Field_solutions/last_completed_pack.csv', last_completed_pack, delimiter=" " ) #to recover the last frequency of FFEM was interrupted if d["freq"] in freq_pack: print("Processed frequencies: ") print(freq_pack) if d["number_of_processors"] > freq_list.shape[0]: n_files = freq_list.shape[0] else: n_files = d["number_of_processors"] complete_impedance = np.zeros((freq_list.shape[0], 3), float) if d["Full_Field_IFFT"] == 1: # for Full IFFT we have to re-sort only impedance results cnt_freq = 0 for core in range(n_files): if (d["CPE_activ"] == 1 or d["current_control"] == 1) and cc_multicontact == False: impedance_get = read_csv(os.environ['PATIENTDIR'] + '/Field_solutions/Impedance' + str(core) + '.csv', delimiter=' ', header=None) impedance = impedance_get.values complete_impedance[cnt_freq:cnt_freq + impedance.shape[0], :] cnt_freq = cnt_freq + impedance.shape[0] if ( d["CPE_activ"] == 1 or d["current_control"] == 1 ) and cc_multicontact == False: # we calculate impedance with FFEM only for these cases sorted_impedance = complete_impedance[ complete_impedance[:, 2].argsort(axis=0)] #sort by freq np.savetxt(os.environ['PATIENTDIR'] + '/Field_solutions/sorted_impedance.csv', sorted_impedance, delimiter=" ") minutes = int((tm.time() - start_paral) / 60) secnds = int(tm.time() - start_paral) - minutes * 60 print("----- parallel calculations took ", minutes, " min ", secnds, " s -----") return True else: inx_compl_sol = 0 complete_solution = np.zeros( (freq_list.shape[0] * Vertices.shape[0], len(d["Phi_vector"]) + 1), float) cnt_freq = 0 for core in range(n_files): hf = h5py.File( os.environ['PATIENTDIR'] + '/Field_solutions/sol_per_contact_cor' + str(core) + '.h5', 'r') lst = list(hf.keys()) result_total = [] for i in lst: a = hf.get(i) a = np.array(a) result_total.append(a) result = np.concatenate(result_total) hf.close() complete_solution[inx_compl_sol:inx_compl_sol + result.shape[0], :] = result inx_compl_sol = inx_compl_sol + result.shape[0] if ( d["CPE_activ"] == 1 or d["current_control"] == 1 ) and cc_multicontact == False: # we calculate impedance with FFEM only for these cases impedance_get = read_csv(os.environ['PATIENTDIR'] + '/Field_solutions/Impedance' + str(core) + '.csv', delimiter=' ', header=None) impedance = impedance_get.values complete_impedance[cnt_freq:cnt_freq + impedance.shape[0], :] = impedance cnt_freq = cnt_freq + impedance.shape[0] if ( d["CPE_activ"] == 1 or d["current_control"] == 1 ) and cc_multicontact == False: # we calculate impedance with FFEM only for these cases sorted_impedance = complete_impedance[ complete_impedance[:, 2].argsort(axis=0)] #sort by freq np.savetxt(os.environ['PATIENTDIR'] + '/Field_solutions/sorted_impedance.csv', sorted_impedance, delimiter=" ") plt.figure(101010) plt.plot(sorted_impedance[:, 0], sorted_impedance[:, 1], marker='o') #plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,ncol=2, mode="expand", borderaxespad=0.) ### ncol=2, mode="expand", borderaxespad=0.) plt.xlabel(r'Re(Z), $\Omega$') plt.ylabel(r'Im(Z), $\Omega$') plt.grid(True) plt.savefig(os.environ['PATIENTDIR'] + '/Images/Imp_plot.eps', format='eps', dpi=1000) Ampl_imp = np.zeros(sorted_impedance.shape[0], dtype=float) for i_fr in range(sorted_impedance.shape[0]): Ampl_imp[i_fr] = np.sqrt( sorted_impedance[i_fr, 0] * sorted_impedance[i_fr, 0] + sorted_impedance[i_fr, 1] * sorted_impedance[i_fr, 1]) plt.figure(2) plt.plot(sorted_impedance[:, 2], Ampl_imp[:], marker='o') plt.xscale("log") plt.xlabel('f, Hz') plt.ylabel(r'Ampl(Z), $\Omega$') plt.grid(True) plt.savefig(os.environ['PATIENTDIR'] + '/Images/Imp_Ampl_plot.eps', format='eps', dpi=1000) minutes = int((tm.time() - start_paral) / 60) secnds = int(tm.time() - start_paral) - minutes * 60 print("----- Parallel calculations took ", minutes, " min ", secnds, " s -----\n") sort_full_solution(d, freq_list, complete_solution, number_of_points) del complete_solution if Field_on_VTA == 1: d["Full_Field_IFFT"] = 1 return True
def get_field_with_floats(mesh_sol, active_index, Domains, subdomains, boundaries_sol, default_material, element_order, anisotropy, frequenc, Laplace_mode, Solver_type, calc_with_MPI=False, kappa=False): set_log_active(False) #turns off debugging info parameters['linear_algebra_backend'] = 'PETSc' if Laplace_mode == 'EQS': Solver_type = 'MUMPS' # always direct solver for EQS when multiple floats if calc_with_MPI == False: [cond_GM, perm_GM] = DielectricProperties(3).get_dielectrics( frequenc ) #3 for grey matter and so on (numeration as in voxel_data) [cond_WM, perm_WM] = DielectricProperties(2).get_dielectrics(frequenc) [cond_CSF, perm_CSF] = DielectricProperties(1).get_dielectrics(frequenc) [cond_default, perm_default ] = DielectricProperties(default_material).get_dielectrics(frequenc) from GUI_inp_dict import d as d_encap [cond_encap, perm_encap] = DielectricProperties( d_encap['encap_tissue_type']).get_dielectrics(frequenc) cond_encap = cond_encap * d_encap['encap_scaling_cond'] perm_encap = perm_encap * d_encap['encap_scaling_perm'] conductivities = [cond_default, cond_GM, cond_WM, cond_CSF, cond_encap] rel_permittivities = [ perm_default, perm_GM, perm_WM, perm_CSF, perm_encap ] # to get conductivity (and permittivity if EQS formulation) mapped accrodingly to the subdomains. k_val_r is just a list of conductivities (S/mm!) in a specific order to scale the cond. tensor from FEM_in_spectrum import get_dielectric_properties_from_subdomains kappa, k_val_r = get_dielectric_properties_from_subdomains( mesh_sol, subdomains, Laplace_mode, Domains.Float_contacts, conductivities, rel_permittivities, frequenc) if anisotropy == 1: # order xx,xy,xz,yy,yz,zz c00 = MeshFunction("double", mesh_sol, 3, 0.0) c01 = MeshFunction("double", mesh_sol, 3, 0.0) c02 = MeshFunction("double", mesh_sol, 3, 0.0) c11 = MeshFunction("double", mesh_sol, 3, 0.0) c12 = MeshFunction("double", mesh_sol, 3, 0.0) c22 = MeshFunction("double", mesh_sol, 3, 0.0) if calc_with_MPI == True: #load predefined Tensor Cond_tensor = load_scaled_cond_tensor(c00, c01, c02, c11, c12, c22, mesh_sol) else: # load the unscaled diffusion tensor (should be normalized beforehand) hdf = HDF5File( mesh_sol.mpi_comm(), "Results_adaptive/Tensors_to_solve_num_el_" + str(mesh_sol.num_cells()) + ".h5", "r") hdf.read(c00, "/c00") hdf.read(c01, "/c01") hdf.read(c02, "/c02") hdf.read(c11, "/c11") hdf.read(c12, "/c12") hdf.read(c22, "/c22") hdf.close() unscaled_tensor = [c00, c01, c02, c11, c12, c22] # to get tensor scaled by the conductivity map (twice send frequenc to always get unscaled ellipsoid tensor for visualization) from FEM_in_spectrum import get_scaled_cond_tensor Cond_tensor = get_scaled_cond_tensor(mesh_sol, subdomains, frequenc, frequenc, unscaled_tensor, k_val_r) else: Cond_tensor = False #just to initialize from FEM_in_spectrum import get_solution_space_and_Dirichlet_BC V_space = get_solution_space_and_Dirichlet_BC(1, mesh_sol, boundaries_sol, element_order, Laplace_mode, Domains.Contacts, Domains.fi, only_space=True) facets = MeshFunction('size_t', mesh_sol, 2) facets.set_all(0) # here we have a custom way to assign Dirichlet BC dirichlet_bc = [] float_surface = 2 active_floats = 0 # assign only the chosen active contact and the ground, other should be just marked on the mesh (starting from 2) #print("Contacts: ",Domains.Contacts) #print("fi: ",Domains.fi) #print("active_index: ",active_index) #print("ponteial: ", Domains.fi[active_index]) for bc_i in range(len(Domains.Contacts)): if bc_i == active_index or Domains.fi[bc_i] == 0.0: #print("one") if Laplace_mode == 'EQS': dirichlet_bc.append( DirichletBC(V_space.sub(0), Domains.fi[bc_i], boundaries_sol, Domains.Contacts[bc_i])) dirichlet_bc.append( DirichletBC(V_space.sub(1), Constant(0.0), boundaries_sol, Domains.Contacts[bc_i])) else: dirichlet_bc.append( DirichletBC(V_space, Domains.fi[bc_i], boundaries_sol, Domains.Contacts[bc_i])) if bc_i == active_index: facets.array()[boundaries_sol.array() == Domains.Contacts[bc_i]] = 1 else: facets.array()[boundaries_sol.array() == Domains.Contacts[ bc_i]] = float_surface #it will not be assigned to always floating contacts float_surface = float_surface + 1 active_floats = active_floats + 1 #definitions for integrators dx = Measure("dx", domain=mesh_sol) dsS = Measure("ds", domain=mesh_sol, subdomain_data=facets) dsS_int = Measure("dS", domain=mesh_sol, subdomain_data=facets) #An_surface_size=assemble(1.0*dsS_int(1)) #Cat_surface_size=assemble(1.0*dsS_int(2)) #print "Anode size: " #print An_surface_size # to solve the Laplace equation div(kappa*grad(phi))=0 (variational form: a(u,v)=L(v)) from FEM_in_spectrum import define_variational_form_and_solve phi_sol = define_variational_form_and_solve( V_space, dirichlet_bc, kappa, Laplace_mode, Cond_tensor, Solver_type ) # with multiple floats MUMPS is the most stable though slow if Laplace_mode == 'EQS': (phi_r_sol, phi_i_sol) = phi_sol.split(deepcopy=True) else: phi_r_sol = phi_sol phi_i_sol = Function(V_space) phi_i_sol.vector()[:] = 0.0 Float_potentials_real = np.zeros(active_floats, float) Float_potentials_imag = np.zeros(active_floats, float) float_surface = 2 #float indicies start from 2 # assess the floating potential by integrating over the contact's surface for fl_in in range(active_floats): Float_surface_size = assemble(1.0 * dsS_int(float_surface)) Float_potentials_real[float_surface - 2] = assemble( phi_r_sol * dsS_int(float_surface)) / Float_surface_size if Laplace_mode == 'EQS': Float_potentials_imag[float_surface - 2] = assemble( phi_i_sol * dsS_int(float_surface)) / Float_surface_size float_surface = float_surface + 1 # to get manual projections for the E-field from FEM_in_spectrum_multicontact import get_E_field E_field, E_field_im = get_E_field(mesh_sol, element_order, Laplace_mode, phi_r_sol, phi_i_sol) #if QS, E_field_im is a null function n = FacetNormal(mesh_sol) if Laplace_mode == 'EQS': if Cond_tensor != False: j_dens_real_contact = dot( Cond_tensor * E_field, -1 * n)('-') * dsS_int(1) - dot( kappa[1] * E_field_im, -1 * n)('-') * dsS_int(1) j_dens_im_contact = dot( Cond_tensor * E_field_im, -1 * n)('-') * dsS_int(1) + dot( kappa[1] * E_field, -1 * n)('-') * dsS_int(1) else: j_dens_real_contact = dot( kappa[0] * E_field, -1 * n)('-') * dsS_int(1) - dot( kappa[1] * E_field_im, -1 * n)('-') * dsS_int(1) j_dens_im_contact = dot( kappa[0] * E_field_im, -1 * n)('-') * dsS_int(1) + dot( kappa[1] * E_field, -1 * n)('-') * dsS_int(1) J_real = assemble(j_dens_real_contact) J_im = assemble(j_dens_im_contact) return Float_potentials_real, Float_potentials_imag, J_real, J_im else: if Cond_tensor != False: j_dens_real_contact = dot(Cond_tensor * E_field, -1 * n)('-') * dsS_int(1) else: j_dens_real_contact = dot(kappa[0] * E_field, -1 * n)('-') * dsS_int(1) J_real = assemble(j_dens_real_contact) #print("Shape float potentials: ",Float_potentials_real.shape[0]) return Float_potentials_real, 0.0, J_real, 0.0