def adapt_mesh(region,mesh_initial,boundaries_initial,subdomains_assigned_initial,MRI_param,DTI_param,Domains,d,cc_multicontact,num_proc,anisotropy,Field_calc_param,previous_results):

    print("----- Conducting "+region+" -----")
    start_adapt_region=time_lib.clock()

    save_mesh('initial_for_the_step',mesh_initial,boundaries_initial,subdomains_assigned_initial)

    if d["FEniCS_MPI"]==True:
        if cc_multicontact==True:
            from Math_module_floating_MPI import get_solutions,get_field_on_points
        else:
            from Math_module_MPI_only_FEniCS import get_solutions,get_field_on_points
    else:
        if cc_multicontact==True:
            from Math_module_hybrid_floating import compute_field_with_superposition,get_field_on_points
        else:
            from Math_module_hybrid import get_field,get_field_on_points


    from CSF_refinement_new import mesh_refiner

    if anisotropy==1:
        from Tissue_marking_new import get_cellmap_tensors
        subdomains=get_cellmap_tensors(mesh_initial,subdomains_assigned_initial,Domains,MRI_param,DTI_param,d["default_material"])
    else:
        from Tissue_marking_new import get_cellmap
        subdomains=get_cellmap(mesh_initial,subdomains_assigned_initial,Domains,MRI_param,d["default_material"])

    if d["current_control"]==1:     #in this case we need to check current convergence
        current_checked=0       #phi_error will be defined after phi evaluation on the initial mesh
    else:
        current_checked=1
        Phi_vector=[x for x in d["Phi_vector"] if x is not None]
        if Field_calc_param.external_grounding==True:
            Phi_vector.append(0.0)
        phi_error=abs((max(Phi_vector)-min(Phi_vector))*d["Adaptive_frac_div"])


    if region == 'it_outside_ROI':
        ref_mode = 0
    elif region == 'it_on_contact':
        ref_mode = 1
        current_checked=0           #always check current when refining around contacts
        if d["current_control"]==0:     #in this case we need to check current convergence
            d["rel_div_current"]=0.012
            print("Although VC mode is used, current convergence will be checked during refinement around contacts with 1.2% rel. deviation. You can change the threshold in Mesh_adaption_hybrid.py")

        if d["rel_div"]>=0.01:
            d["rel_div"] = d["rel_div"]
        else:
            d["rel_div"] = 0.01          #always fixed to 1% to avoid flickering
            print("Rel. error threshold during refinement around contacts is set to 1% (to discard flickering effect)")
    elif region == 'it_in_ROI':
        ref_mode = 2

    ref_it=1    #first iteration (yes, here we start from 1)

    if previous_results[0] == -1:    #no previous results available
        #Calculate on the initial mesh
        if d["FEniCS_MPI"]==True:
            save_mesh_and_kappa_to_h5(mesh_initial,subdomains,boundaries_initial,Field_calc_param)
            if cc_multicontact==True:
                subprocess.call(["mpirun", "-np", "{}".format(num_proc), "python3", "Math_module_floating_MPI.py"])
            else:
                subprocess.call(["mpirun", "-np", "{}".format(num_proc), "python3", "Math_module_MPI_only_FEniCS.py"])

            Phi_r,Phi_im,Field_real,Field_imag,max_E,J_r,J_im,j_dens_real,j_dens_im=get_solutions(d["EQS_core"],Field_calc_param.frequenc,Field_calc_param.element_order)
        else:
            if cc_multicontact==True:
                [Phi_r,Phi_im,Field_real,Field_imag,max_E,J_r,J_im,j_dens_real,j_dens_im]=compute_field_with_superposition(mesh_initial,Domains,subdomains_assigned_initial,subdomains,boundaries_initial,Field_calc_param)
            else:
                [Phi_r,Phi_im,Field_real,Field_imag,max_E,J_r,J_im,j_dens_real,j_dens_im]=get_field(mesh_initial,Domains,subdomains,boundaries_initial,Field_calc_param)

        Phi_amp_on_neuron =get_field_on_points(Phi_r,Phi_im,d["current_control"],J_r,J_im)   #To calculate the second norm of the Field
        previous_results = [Phi_r,Phi_im,Field_real,Field_imag,J_r,J_im,j_dens_real,j_dens_im,Phi_amp_on_neuron,max_E]
    else:
        Phi_r,Phi_im,Field_real,Field_imag,J_r,J_im,j_dens_real,j_dens_im,Phi_amp_on_neuron,max_E=previous_results[:]

    if d["current_control"] == True:
        if d["EQS_core"]=='EQS':
            #not the best approach, but both should be on the Dirichlet BCs
            max_phi_r=max(Phi_r.vector()[:])
            max_phi_im=max(Phi_im.vector()[:])

            min_phi_r=min(Phi_r.vector()[:])
            min_phi_im=min(Phi_im.vector()[:])

            phi_error=abs((np.sqrt((max_phi_r-min_phi_r)**2+(max_phi_im-min_phi_im)**2))*d["Adaptive_frac_div"])   #should be scaled
        else:
            phi_error=abs((max(Phi_r.vector()[:])-min(Phi_r.vector()[:]))*d["Adaptive_frac_div"])   #should be scaled

    print("Absolute error threshold on neuron compartments: ",phi_error,"V")

    # mesh refined uniformly in the specified region by ref_mode
    print("\n--- Initial uniform refinement step for "+region)
    cells_ref=mark_cells_start(mesh_initial,ref_mode,subdomains_assigned_initial, Domains)
    [mesh_new,boundaries_new,subdomains_assigned_new]=mesh_refiner(mesh_initial,boundaries_initial,subdomains_assigned_initial,cells_ref,Domains,cc_multicontact)

    #here we start to refine
    while (cells_ref.where_equal(True)):        # if True, then there are some cells marked for refinement

        if anisotropy==1:
            subdomains_new=get_cellmap_tensors(mesh_new,subdomains_assigned_new,Domains,MRI_param,DTI_param,d["default_material"])
        else:
            subdomains_new=get_cellmap(mesh_new,subdomains_assigned_new,Domains,MRI_param,d["default_material"])

        if d["FEniCS_MPI"]==True:
            save_mesh_and_kappa_to_h5(mesh_new,subdomains_new,boundaries_new,Field_calc_param)
            if cc_multicontact == True:
                subprocess.call(["mpirun", "-np", "{}".format(num_proc), "python3", "Math_module_floating_MPI.py"])
            else:
                subprocess.call(["mpirun", "-np", "{}".format(num_proc), "python3", "Math_module_MPI_only_FEniCS.py"])
            Phi_r_new,Phi_im_new,Field_real_new,Field_imag_new,max_E_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new=get_solutions(d["EQS_core"],Field_calc_param.frequenc,Field_calc_param.element_order)
        else:
            if cc_multicontact == True:
                [Phi_r_new,Phi_im_new,Field_real_new,Field_imag_new,max_E_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new]=compute_field_with_superposition(mesh_new,Domains,subdomains_assigned_new,subdomains_new,boundaries_new,Field_calc_param)
            else:
                [Phi_r_new,Phi_im_new,Field_real_new,Field_imag_new,max_E_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new]=get_field(mesh_new,Domains,subdomains_new,boundaries_new,Field_calc_param)



        Phi_amp_on_neuron_new=get_field_on_points(Phi_r_new,Phi_im_new,d["current_control"],J_r_new,J_im_new)


        #check E-field convergence first (always, even if only current did not converge)
        if ref_it==1:       #on the first iteration we will mark cells on the initial mesh
            cells_ref=mark_cells(Field_calc_param.external_grounding,mesh_initial,ref_mode,Field_real,Field_imag,Field_real_new,Field_imag_new,Phi_amp_on_neuron_new,Phi_amp_on_neuron,max_E_new,d["rel_div"],phi_error,subdomains_assigned_initial,Domains)
        else:
            cells_ref=mark_cells(Field_calc_param.external_grounding,mesh_new,ref_mode,Field_real,Field_imag,Field_real_new,Field_imag_new,Phi_amp_on_neuron_new,Phi_amp_on_neuron,max_E_new,d["rel_div"],phi_error,subdomains_assigned_new,Domains)

        if (cells_ref.where_equal(True)):
            ref_due_to_phi_dev=1

        ###### check current convergence if necessary #####
        if current_checked==0 and not(cells_ref.where_equal(True)):
            print("Checking current convergence for " + region)
            if check_current_conv(J_r,J_im,J_r_new,J_im_new,d["rel_div_current"]):           # True if current deviation above rel_div_current
                if ref_it==1:       #marking will be on the initial mesh
                    cells_ref=mark_cell_loc_J(Field_calc_param.external_grounding,subdomains_assigned_initial,j_dens_real,j_dens_im,j_dens_real_new,j_dens_im_new,mesh_initial,mesh_new,ref_mode,1,Domains,d["rel_div_current"])
                elif ref_it==2:
                    cells_ref=mark_cell_loc_J(Field_calc_param.external_grounding,subdomains_assigned_initial,j_dens_real,j_dens_im,j_dens_real_new,j_dens_im_new,mesh_initial,mesh_new,ref_mode,2,Domains,d["rel_div_current"])
                else:
                    mesh_old = Mesh(os.environ['PATIENTDIR']+"/Results_adaptive/mesh_adapt.xml.gz")
                    subdomains_assigned_old = MeshFunction('size_t',mesh_old,os.environ['PATIENTDIR']+'/Results_adaptive/subdomains_assigned_adapt.xml')
                    if ref_due_to_phi_dev==0:   #if previous refinement due to current, refine on mesh_new
                        cells_ref=mark_cell_loc_J(Field_calc_param.external_grounding,subdomains_assigned_old,j_dens_real,j_dens_im,j_dens_real_new,j_dens_im_new,mesh_old,mesh_new,ref_mode,2,Domains,d["rel_div_current"])
                    else:                       #else, refine on mesh
                        cells_ref=mark_cell_loc_J(Field_calc_param.external_grounding,subdomains_assigned_old,j_dens_real,j_dens_im,j_dens_real_new,j_dens_im_new,mesh_old,mesh_new,ref_mode,1,Domains,d["rel_div_current"])

                if not (cells_ref.where_equal(True)):
                    current_checked=1
                    print("Current did not converge, but nothing marked to refine! Consider decreasing threshold_current_in_element in Mesh_adaptation.py")
                else:
                    if ref_it>2:
                        if ref_due_to_phi_dev==1:   #if this is a refinement due to current right after phi_dev check, refine on mesh (resaved as mesh_new). Otherwise, on mesh_new
                            Phi_r_new,Phi_im_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new,Field_real_new,Field_imag_new,Phi_amp_on_neuron_new,max_E_new=(Phi_r,Phi_im,J_r,J_im,j_dens_real,j_dens_im,Field_real,Field_imag,Phi_amp_on_neuron,max_E)
                            del mesh_new,boundaries_new,subdomains_assigned_new
                            mesh_new,boundaries_new,subdomains_assigned_new=load_mesh('adapt')

                    ref_due_to_phi_dev=0   #the refinement will be conducted due to current deviation

            else:
                current_checked=1
                print("Current converged\n")


        if not(cells_ref.where_equal(True)) and ref_it==2:       # written on the envelope.   if we refine adaptively only once, we want to evaluate mesh that we just refined. Otherwise, we will evaluate already saved mesh
            save_mesh('adapt_it2',mesh_new,boundaries_new,subdomains_assigned_new)
            Phi_r,Phi_im,J_r,J_im,j_dens_real,j_dens_im,Field_real,Field_imag,Phi_amp_on_neuron,max_E=(Phi_r_new,Phi_im_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new,Field_real_new,Field_imag_new,Phi_amp_on_neuron_new,max_E_new)
            previous_results = [Phi_r_new,Phi_im_new,Field_real_new,Field_imag_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new,Phi_amp_on_neuron_new,max_E_new]

        # if we got local convergence, let us check with uniform refinement again and mark cells, where high deviation occurs
        if not (cells_ref.where_equal(True)) and ref_it>1:
            print("\n--- Uniform refinement step for "+ region)
            if ref_it==2:
                mesh,boundaries,subdomains_assigned=load_mesh('adapt_it2')
            else:
                mesh,boundaries,subdomains_assigned=load_mesh('adapt')

            #uniform refinement
            cells_ref=mark_cells_start(mesh,ref_mode,subdomains_assigned, Domains)
            [mesh_uni,boundaries_uni,subdomains_assigned_uni]=mesh_refiner(mesh,boundaries,subdomains_assigned,cells_ref,Domains,cc_multicontact)

            if not(os.path.isfile(os.environ['PATIENTDIR']+'/Results_adaptive/cells_to_ref_after_uni_'+str(mesh_uni.num_cells())+'.h5')):     #check whether calculations for this uniform refinement were already conducted
                if anisotropy==1:
                    subdomains_uni=get_cellmap_tensors(mesh_uni,subdomains_assigned_uni,Domains,MRI_param,DTI_param,d["default_material"])
                else:
                    subdomains_uni=get_cellmap(mesh_uni,subdomains_assigned_uni,Domains,MRI_param,d["default_material"])

                if d["FEniCS_MPI"]==True:
                    save_mesh_and_kappa_to_h5(mesh_uni,subdomains_uni,boundaries_uni,Field_calc_param)
                    if cc_multicontact == True:
                        subprocess.call(["mpirun", "-np", "{}".format(num_proc), "python3", "Math_module_floating_MPI.py"])
                    else:
                        subprocess.call(["mpirun", "-np", "{}".format(num_proc), "python3", "Math_module_MPI_only_FEniCS.py"])
                    [Phi_r_uni,Phi_im_uni,Field_real_uni,Field_imag_uni,max_E_uni,J_r_uni,J_im_uni,j_dens_real_uni,j_dens_im_uni]=get_solutions(d["EQS_core"],Field_calc_param.frequenc,Field_calc_param.element_order)
                else:
                    if cc_multicontact == True:
                        [Phi_r_uni,Phi_im_uni,Field_real_uni,Field_imag_uni,max_E_uni,J_r_uni,J_im_uni,j_dens_real_uni,j_dens_im_uni]=compute_field_with_superposition(mesh_uni,Domains,subdomains_assigned_uni,subdomains_uni,boundaries_uni,Field_calc_param)
                    else:
                        [Phi_r_uni,Phi_im_uni,Field_real_uni,Field_imag_uni,max_E_uni,J_r_uni,J_im_uni,j_dens_real_uni,j_dens_im_uni]=get_field(mesh_uni,Domains,subdomains_uni,boundaries_uni,Field_calc_param)

                Phi_amp_on_neuron_uni=get_field_on_points(Phi_r_uni,Phi_im_uni,d["current_control"],J_r_uni,J_im_uni)
                cells_ref=mark_cells(Field_calc_param.external_grounding,mesh,ref_mode,Field_real,Field_imag,Field_real_uni,Field_imag_uni,Phi_amp_on_neuron_uni,Phi_amp_on_neuron,max_E_uni,d["rel_div"],phi_error,subdomains_assigned,Domains)

                hdf = HDF5File(mesh.mpi_comm(), os.environ['PATIENTDIR']+'/Results_adaptive/cells_to_ref_after_uni_'+str(mesh_uni.num_cells())+'.h5', 'w')
                hdf.write(cells_ref, "/cells_ref_after_uni")
                hdf.close()
                np.savetxt(os.environ['PATIENTDIR']+'/Results_adaptive/current_in_uni_ref_'+str(mesh_uni.num_cells())+'.csv', np.array([J_r_uni,J_im_uni]), delimiter=" ")
            else:       #the field was already computed for this uniform refinement
                print("Cells for refinement after uniform check were loaded from the previous iteration\n")
                hdf = HDF5File(mesh.mpi_comm(), os.environ['PATIENTDIR']+'/Results_adaptive/cells_to_ref_after_uni_'+str(mesh_uni.num_cells())+'.h5', 'r')
                cells_ref = MeshFunction('bool', mesh,3)
                hdf.read(cells_ref, "/cells_ref_after_uni")
                hdf.close()

                [J_r_uni,J_im_uni]=np.genfromtxt(os.environ['PATIENTDIR']+'/Results_adaptive/current_in_uni_ref_'+str(mesh_uni.num_cells())+'.csv', delimiter=' ')

            mesh_check=refine(mesh, cells_ref)   #we need to check whether it leads to mesh_new
            num_cells_mesh_check=mesh_check.num_cells()

            file=File(os.environ['PATIENTDIR']+'/Results_adaptive/cells_ref_after_uni.pvd')
            file<<cells_ref

            del mesh_check

            if mesh_new.num_cells()<num_cells_mesh_check or (ref_due_to_phi_dev==0 and mesh_new.num_cells()!=num_cells_mesh_check):   #use mesh to refine further (for this you will have to resave it as mesh_new)
                Phi_r_new,Phi_im_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new,Field_real_new,Field_imag_new,Phi_amp_on_neuron_new,max_E_new=(Phi_r,Phi_im,J_r,J_im,j_dens_real,j_dens_im,Field_real,Field_imag,Phi_amp_on_neuron,max_E)
                del mesh_new,boundaries_new,subdomains_assigned_new
                hdf = HDF5File(mesh.mpi_comm(), os.environ['PATIENTDIR']+'/Results_adaptive/cells_to_ref_after_uni_'+str(mesh_uni.num_cells())+'.h5', 'r')
                cells_ref = MeshFunction('bool', mesh,3)
                hdf.read(cells_ref, "/cells_ref_after_uni")
                hdf.close()
                if ref_it==2:
                    mesh_new,boundaries_new,subdomains_assigned_new=load_mesh('adapt_it2')
                else:
                    mesh_new,boundaries_new,subdomains_assigned_new=load_mesh('adapt')
            elif mesh_new.num_cells()==num_cells_mesh_check and cells_ref.where_equal(True):   #if mesh_uni and mesh_new are the same after current-based ref, switch status to phi-based
                ref_due_to_phi_dev=1

            if check_current_conv(J_r,J_im,J_r_uni,J_im_uni,d["rel_div_current"]):
                print("Current ref. will be conducted only if deviation on neuron compartments was high")
                current_checked=0
            else:
                if ref_mode==1:   #
                    if cells_ref.where_equal(True):
                        print("After uniform check, the current converged, the iteration is complete (only when refining around the contacts)")
                        cells_ref.set_all(False)

            ###
            #if uniform refinement on mesh revealed deviation, but number of marked cells is <= than in mesh_new, then uniformly refine mesh_new. Do this step only if the last local refinement was due to phi ref. If current ref, refine on mesh (no danger of repetition as we have a different criterion)
            if (cells_ref.where_equal(True) and ref_it!=2 and (mesh_new.num_cells()>=num_cells_mesh_check) and ref_due_to_phi_dev==1):       #if mesh and mesh_uni have a high deviation in the solution, then create new mesh_uni from mesh_new using uniform refinement (otherwise it might stuck in the loop mesh-mesh_uni-mesh_new-mesh)
                cells_ref=mark_cells_start(mesh_new,ref_mode,subdomains_assigned_new, Domains)
                print("Deviation is high, now uniformly refining mesh_new")
                save_mesh('adapt',mesh_new,boundaries_new,subdomains_assigned_new)

                [mesh_uni,boundaries_uni,subdomains_assigned_uni]=mesh_refiner(mesh_new,boundaries_new,subdomains_assigned_new,cells_ref,Domains,cc_multicontact)

                if anisotropy==1:
                    subdomains_uni=get_cellmap_tensors(mesh_uni,subdomains_assigned_uni,Domains,MRI_param,DTI_param,d["default_material"])
                else:
                    subdomains_uni=get_cellmap(mesh_uni,subdomains_assigned_uni,Domains,MRI_param,d["default_material"])

                if d["FEniCS_MPI"]==True:
                    save_mesh_and_kappa_to_h5(mesh_uni,subdomains_uni,boundaries_uni,Field_calc_param)
                    if cc_multicontact==True:
                        subprocess.call(["mpirun", "-np", "{}".format(num_proc), "python3", "Math_module_floating_MPI.py"])
                    else:
                        subprocess.call(["mpirun", "-np", "{}".format(num_proc), "python3", "Math_module_MPI_only_FEniCS.py"])
                    [Phi_r_uni,Phi_im_uni,Field_real_uni,Field_imag_uni,max_E_uni,J_r_uni,J_im_uni,j_dens_real_uni,j_dens_im_uni]=get_solutions(d["EQS_core"],Field_calc_param.frequenc,Field_calc_param.element_order)
                else:
                    if cc_multicontact==True:
                        [Phi_r_uni,Phi_im_uni,Field_real_uni,Field_imag_uni,max_E_uni,J_r_uni,J_im_uni,j_dens_real_uni,j_dens_im_uni]=compute_field_with_superposition(mesh_uni,Domains,subdomains_assigned_uni,subdomains_uni,boundaries_uni,Field_calc_param)
                    else:
                        [Phi_r_uni,Phi_im_uni,Field_real_uni,Field_imag_uni,max_E_uni,J_r_uni,J_im_uni,j_dens_real_uni,j_dens_im_uni]=get_field(mesh_uni,Domains,subdomains_uni,boundaries_uni,Field_calc_param)

                Phi_amp_on_neuron_uni=get_field_on_points(Phi_r_uni,Phi_im_uni,d["current_control"],J_r_uni,J_im_uni)

                #for stability
                del mesh_new,boundaries_new,subdomains_assigned_new
                mesh_new,boundaries_new,subdomains_assigned_new=load_mesh('adapt')

                cells_ref=mark_cells(Field_calc_param.external_grounding,mesh_new,ref_mode,Field_real_new,Field_imag_new,Field_real_uni,Field_imag_uni,Phi_amp_on_neuron_uni,Phi_amp_on_neuron_new,max_E_uni,d["rel_div"],phi_error,subdomains_assigned_new,Domains)

                if d["current_control"]==1 or ref_mode==1:
                    if check_current_conv(J_r_new,J_im_new,J_r_uni,J_im_uni,d["rel_div_current"]):
                        print("Current ref. will be conducted only if deviation on neuron compartments was high")
                        current_checked=0

                #save field solution
                hdf = HDF5File(mesh.mpi_comm(), os.environ['PATIENTDIR']+'/Results_adaptive/cells_to_ref_after_uni_'+str(mesh_uni.num_cells())+'.h5', 'w')
                hdf.write(cells_ref, "/cells_ref_after_uni")
                hdf.close()
                np.savetxt(os.environ['PATIENTDIR']+'/Results_adaptive/current_in_uni_ref_'+str(mesh_uni.num_cells())+'.csv', np.array([J_r_uni,J_im_uni]), delimiter=" ")

                if not (cells_ref.where_equal(True)):
                    previous_results = [Phi_r_new,Phi_im_new,Field_real_new,Field_imag_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new,Phi_amp_on_neuron_new,max_E_new]



        #exiting from here if no cells marked, otherwise a new iteration
        if not (cells_ref.where_equal(True)):
            if ref_it==1:
                print("mesh meets the requirements (or no cells were marked for refinement) "+region+" was completed\n")
                save_mesh(region,mesh_initial,boundaries_initial,subdomains_assigned_initial)
                if ref_mode == 2:
                    save_mesh('adapt',mesh_initial,boundaries_initial,subdomains_assigned_initial)
            elif ref_it==2:
                print("mesh_new meets the requirements (or no cells were marked for refinement) "+region+" was completed\n")
                mesh_2it,boundaries_2it,subdomains_assigned_2it=load_mesh('adapt_it2')
                save_mesh(region,mesh_2it,boundaries_2it,subdomains_assigned_2it)
                if ref_mode == 2:
                    save_mesh('adapt',mesh_initial,boundaries_initial,subdomains_assigned_initial)
            else:
                print("mesh_new meets the requirements (or no cells were marked for refinement) "+region+" was completed\n")
                mesh_adapted,boundaries_adapted,subdomains_assigned_adapted=load_mesh('adapt')
                save_mesh(region,mesh_adapted,boundaries_adapted,subdomains_assigned_adapted)

        else:
            print("--- Local refinement step for "+region)
            if ref_it==1:
                mesh_initial,boundaries_initial,subdomains_assigned_initial=load_mesh('initial_for_the_step')   #for stability
                [mesh_new,boundaries_new,subdomains_assigned_new]=mesh_refiner(mesh_initial,boundaries_initial,subdomains_assigned_initial,cells_ref,Domains,cc_multicontact)
                print("mesh size after adaptive refinement: ", mesh_new.num_cells())
                ref_it=ref_it+1
            else:
                Phi_r,Phi_im,J_r,J_im,j_dens_real,j_dens_im,Field_real,Field_imag,Phi_amp_on_neuron,max_E=(Phi_r_new,Phi_im_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new,Field_real_new,Field_imag_new,Phi_amp_on_neuron_new,max_E_new)
                previous_results = [Phi_r_new,Phi_im_new,Field_real_new,Field_imag_new,J_r_new,J_im_new,j_dens_real_new,j_dens_im_new,Phi_amp_on_neuron_new,max_E_new]
                ref_it=ref_it+1
                save_mesh('adapt',mesh_new,boundaries_new,subdomains_assigned_new)
                [mesh_new,boundaries_new,subdomains_assigned_new]=mesh_refiner(mesh_new,boundaries_new,subdomains_assigned_new,cells_ref,Domains,cc_multicontact)

    minutes=int((time_lib.clock() - start_adapt_region)/60)
    secnds=int(time_lib.clock() - start_adapt_region)-minutes*60
    print("--- For "+region+" was adapted in ",minutes," min ",secnds," s \n")

    status=1        #for now always 1

    return previous_results,status
Example #2
0
def Refine_CSF(MRI_param,
               DTI_param,
               Scaling,
               Domains,
               Field_calc_param,
               rel_div,
               CSF_frac_div,
               CSF_ref_add,
               EQS_mode,
               cc_multicontact,
               ref_freq,
               Best_scaling=0,
               scaling_old=0):

    start_CSF_refinement = tim.clock()

    if cc_multicontact == True:
        from Math_module_hybrid_floating import compute_field_with_superposition, get_field_on_points
    else:
        from Math_module_hybrid import get_field, get_field_on_points

    scaling_old = float(scaling_old)
    Scaling = float(Scaling)
    Best_scaling = float(Best_scaling)

    if Field_calc_param.anisotropy == 1:
        from Tissue_marking_new import get_cellmap_tensors
    else:
        from Tissue_marking_new import get_cellmap
    '''load results and mesh from the most refined iteration if available'''
    if Best_scaling != 0:
        Phi_amp_on_neuron_old_get = read_csv(os.environ['PATIENTDIR'] +
                                             '/CSF_ref/Field_on_points' +
                                             str(Best_scaling) + '.csv',
                                             delimiter=' ',
                                             header=None)
        Phi_amp_on_neuron_old = Phi_amp_on_neuron_old_get.values

        mesh = Mesh(os.environ['PATIENTDIR'] + '/CSF_ref/mesh_adapt_CSF' +
                    str(scaling_old) + '.xml.gz')
        boundaries = MeshFunction(
            'size_t', mesh, os.environ['PATIENTDIR'] +
            '/CSF_ref/boundaries_adapt_CSF' + str(scaling_old) + '.xml')
        subdomains_assigned = MeshFunction(
            'size_t', mesh, os.environ['PATIENTDIR'] +
            '/CSF_ref/subdomains_assigned_adapt_CSF' + str(scaling_old) +
            '.xml')
    else:
        if Field_calc_param.external_grounding == False:
            mesh = Mesh(os.environ['PATIENTDIR'] + "/Meshes/Mesh_unref.xml")
            boundaries = MeshFunction(
                'size_t', mesh, os.environ['PATIENTDIR'] +
                '/Meshes/Mesh_unref_facet_region.xml')
            subdomains_assigned = MeshFunction(
                'size_t', mesh, os.environ['PATIENTDIR'] +
                "/Meshes/Mesh_unref_physical_region.xml")
        else:
            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 neuron compartments
    Vertices_neur_get = read_csv(
        os.environ['PATIENTDIR'] +
        '/Neuron_model_arrays/Vert_of_Neural_model_NEURON.csv',
        delimiter=' ',
        header=None)
    Vertices_neur = Vertices_neur_get.values

    if Best_scaling == 0:
        mesh_file = File(os.environ['PATIENTDIR'] + '/CSF_ref/mesh_adapt_CSF' +
                         str(Best_scaling) + '.xml.gz')
        boundaries_file = File(os.environ['PATIENTDIR'] +
                               '/CSF_ref/boundaries_adapt_CSF' +
                               str(Best_scaling) + '.xml')
        subdomains_assigned_file = File(
            os.environ['PATIENTDIR'] +
            '/CSF_ref/subdomains_assigned_adapt_CSF' + str(Best_scaling) +
            '.xml')
        mesh_file << mesh
        boundaries_file << boundaries
        subdomains_assigned_file << subdomains_assigned

        print("Field calculation on the initial mesh")
        if Field_calc_param.anisotropy == 1:
            subdomains = get_cellmap_tensors(mesh, subdomains_assigned,
                                             Domains, MRI_param, DTI_param,
                                             Field_calc_param.default_material)
        else:
            subdomains = get_cellmap(mesh, subdomains_assigned, Domains,
                                     MRI_param,
                                     Field_calc_param.default_material)

        save_mesh_and_subdomains_to_h5(mesh, subdomains, subdomains_assigned,
                                       boundaries, Best_scaling)

        print("CSF_Subdomains_unref file was created")
        file = File(os.environ['PATIENTDIR'] +
                    '/CSF_ref/CSF_Subdomains_unref.pvd')
        file << subdomains, mesh

        if cc_multicontact == True:
            Phi_r_old, Phi_im_old, Field_r_old, Field_im_old, max_E_old, J_r_old, J_im_old, j_dens_real, j_dens_im = compute_field_with_superposition(
                mesh, Domains, subdomains_assigned, subdomains, boundaries,
                Field_calc_param)
        else:
            Phi_r_old, Phi_im_old, Field_r_old, Field_im_old, max_E_old, J_r_old, J_im_old, j_dens_real, j_dens_im = get_field(
                mesh, Domains, subdomains, boundaries, Field_calc_param)

        file = File(os.environ['PATIENTDIR'] + '/CSF_ref/Field_r_' +
                    str(Best_scaling) + '.pvd')
        file << Field_r_old

        Phi_amp_on_neuron_old = get_field_on_points(Phi_r_old, Phi_im_old,
                                                    Field_calc_param.c_c,
                                                    J_r_old, J_im_old)
        np.savetxt(os.environ['PATIENTDIR'] + '/CSF_ref/Field_on_points' +
                   str(Best_scaling) + '.csv',
                   Phi_amp_on_neuron_old,
                   delimiter=" ")

    # load array with the CSF voxels if available, otherwise extract it from the MRI data
    if os.path.isfile(os.environ['PATIENTDIR'] + '/MRI_DTI_derived_data/' +
                      MRI_param.name[:-4] + '_voxel_array_CSF_' +
                      str(CSF_ref_add) + '.npy') or os.path.isfile(
                          os.environ['PATIENTDIR'] + '/MRI_DTI_derived_data/' +
                          MRI_param.name[:-7] + '_voxel_array_CSF_' +
                          str(CSF_ref_add) + '.npy'):
        if MRI_param.name[-2:] == 'gz':
            voxel_array_CSF = np.load(os.environ['PATIENTDIR'] +
                                      '/MRI_DTI_derived_data/' +
                                      MRI_param.name[:-7] +
                                      '_voxel_array_CSF_' + str(CSF_ref_add) +
                                      '.npy')
        else:
            voxel_array_CSF = np.load(os.environ['PATIENTDIR'] +
                                      '/MRI_DTI_derived_data/' +
                                      MRI_param.name[:-4] +
                                      '_voxel_array_CSF_' + str(CSF_ref_add) +
                                      '.npy')

        print("voxel_array_CSF in ", str(CSF_ref_add),
              " mm vicinity is loaded")
    else:
        start_voxel_array_CSF = tim.clock()

        Tissue_array = np.load(os.environ['PATIENTDIR'] +
                               '/MRI_DTI_derived_data/Tissue_array_MRI.npy')
        x_vect = np.genfromtxt(os.environ['PATIENTDIR'] +
                               '/MRI_DTI_derived_data/x_vector_MRI_Box.csv',
                               delimiter=' ')
        y_vect = np.genfromtxt(os.environ['PATIENTDIR'] +
                               '/MRI_DTI_derived_data/y_vector_MRI_Box.csv',
                               delimiter=' ')
        z_vect = np.genfromtxt(os.environ['PATIENTDIR'] +
                               '/MRI_DTI_derived_data/z_vector_MRI_Box.csv',
                               delimiter=' ')

        voxel_array_CSF = np.zeros(
            (Tissue_array.shape[0], 3),
            float)  #array to store all CSF voxels in the specified ROI

        bb = mesh.bounding_box_tree()
        #check the extent of the neuron array (loof for CSF only there + vicinity defined by CSF_ref_add)
        x_neuron_max = max(Vertices_neur[:, 0])
        y_neuron_max = max(Vertices_neur[:, 1])
        z_neuron_max = max(Vertices_neur[:, 2])
        x_neuron_min = min(Vertices_neur[:, 0])
        y_neuron_min = min(Vertices_neur[:, 1])
        z_neuron_min = min(Vertices_neur[:, 2])

        #go over all voxels and check whether it contains CSF and intersect with the mesh
        for x_coord in x_vect:
            for y_coord in y_vect:
                for z_coord in z_vect:

                    x_pos = x_coord - MRI_param.x_vox_size / 2.0
                    y_pos = y_coord - MRI_param.y_vox_size / 2.0
                    z_pos = z_coord - MRI_param.z_vox_size / 2.0

                    if (x_pos <= x_neuron_max + CSF_ref_add
                            and x_pos >= x_neuron_min - CSF_ref_add
                            and y_pos <= y_neuron_max + CSF_ref_add
                            and y_pos >= y_neuron_min - CSF_ref_add
                            and z_pos <= z_neuron_max + CSF_ref_add
                            and z_pos >= z_neuron_min - CSF_ref_add):

                        xv_mri = int(
                            (x_coord) / MRI_param.x_vox_size - 0.000000001
                        )  #defines number of steps to get to the voxels containing x[0] coordinate
                        yv_mri = (
                            int((y_coord) / MRI_param.y_vox_size - 0.000000001)
                        ) * MRI_param.M_x  #defines number of steps to get to the voxels containing x[0] and x[1] coordinates
                        zv_mri = (
                            int((z_coord) / MRI_param.z_vox_size - 0.000000001)
                        ) * MRI_param.M_x * MRI_param.M_y  #defines number of steps to get to the voxels containing x[0], x[1] and x[2] coordinates
                        glob_index = int(xv_mri + yv_mri + zv_mri)

                        pnt = Point(x_pos, y_pos, z_pos)

                        if Tissue_array[
                                glob_index] == 1 and bb.compute_first_entity_collision(
                                    pnt) < mesh.num_cells() * 100:
                            voxel_array_CSF[glob_index, 0] = x_pos
                            voxel_array_CSF[glob_index, 1] = y_pos
                            voxel_array_CSF[glob_index, 2] = z_pos

        voxel_array_CSF = voxel_array_CSF[~np.all(
            voxel_array_CSF == 0.0, axis=1)]  #deletes all zero enteries

        if MRI_param.name[-2:] == 'gz':
            np.save(
                os.environ['PATIENTDIR'] + '/MRI_DTI_derived_data/' +
                MRI_param.name[:-7] + '_voxel_array_CSF_' + str(CSF_ref_add),
                voxel_array_CSF)
        else:
            np.save(
                os.environ['PATIENTDIR'] + '/MRI_DTI_derived_data/' +
                MRI_param.name[:-4] + '_voxel_array_CSF_' + str(CSF_ref_add),
                voxel_array_CSF)

        del Tissue_array
        print(
            "----- voxel_array_CSF for ", str(CSF_ref_add),
            " mm vicinity was prepared in %s seconds -----" %
            (tim.clock() - start_voxel_array_CSF))
    '''Here we pre-refine mesh on elements with CSF voxels'''
    csf_ref = 0
    loaded_from_h5 = 0
    print("refining CSF voxels with scaling ", int(Scaling))
    num_cell_old = mesh.num_cells()

    if os.path.isfile(os.environ['PATIENTDIR'] +
                      '/CSF_ref/Mesh_to_solve_scaling_' + str(Scaling) +
                      '.h5'):
        print(
            "Mesh and tissue mapping was loaded from the refinement at the previous frequency"
        )
        mesh, subdomains, subdomains_assigned, boundaries = load_mesh_and_subdomains_from_h5(
            Scaling)
        loaded_from_h5 = 1
    elif os.path.isfile(
            os.environ['PATIENTDIR'] + '/CSF_ref/mesh_adapt_CSF' +
            str(Scaling) + '.xml.gz'
    ):  #this and not the case above could be only triggered if no computations took place at this scalling at the last frequency (because of the same mesh size)
        if Best_scaling == 0:
            print(
                "No elements were refined during the full CSF refinement, skipping to adaptive mesh refinement (consider decreasing Minimum Element to Voxel Ratio)"
            )
            return 1
        print("skipping scaling ", Scaling)
        mesh_file = File(os.environ['PATIENTDIR'] + '/CSF_ref/mesh_adapt_CSF' +
                         str(Scaling) + '.xml.gz')
        mesh_file << mesh
        boundaries_file = File(os.environ['PATIENTDIR'] +
                               '/CSF_ref/boundaries_adapt_CSF' + str(Scaling) +
                               '.xml')
        subdomains_assigned_file = File(
            os.environ['PATIENTDIR'] +
            '/CSF_ref/subdomains_assigned_adapt_CSF' + str(Scaling) + '.xml')
        boundaries_file << boundaries
        subdomains_assigned_file << subdomains_assigned
        return 0
    else:
        while csf_ref == 0:  #refine mesh until get the required edge size to voxel ratio
            inx_pnt = 0  #to check, how much voxels were processed
            cell_index_list = []
            bb = mesh.bounding_box_tree()

            for i_csf in range(voxel_array_CSF.shape[0]
                               ):  #find cells which contain the CSF voxels
                pnt = Point(voxel_array_CSF[i_csf, 0],
                            voxel_array_CSF[i_csf, 1], voxel_array_CSF[i_csf,
                                                                       2])
                inx_pnt = inx_pnt + 1
                cell_index_list.append(bb.compute_first_entity_collision(pnt))
            cell_index_array = np.asarray(cell_index_list)
            cell_ref = index_cell_marker(mesh, cell_index_array, MRI_param,
                                         Scaling)

            if not (
                    cell_ref.where_equal(True)
            ):  #if any cell was marked for refinement, will return True
                csf_ref = 1

                mesh_file = File(os.environ['PATIENTDIR'] +
                                 '/CSF_ref/mesh_adapt_CSF' + str(Scaling) +
                                 '.xml.gz')
                mesh_file << mesh
                boundaries_file = File(os.environ['PATIENTDIR'] +
                                       '/CSF_ref/boundaries_adapt_CSF' +
                                       str(Scaling) + '.xml')
                subdomains_assigned_file = File(
                    os.environ['PATIENTDIR'] +
                    '/CSF_ref/subdomains_assigned_adapt_CSF' + str(Scaling) +
                    '.xml')
                boundaries_file << boundaries
                subdomains_assigned_file << subdomains_assigned

                print("Number of cells after CSF refinement iteration: ",
                      mesh.num_cells())

                if num_cell_old == mesh.num_cells():
                    if Best_scaling == 0:
                        print(
                            "No elements were refined during the full CSF refinement, skipping to adaptive mesh refinement (consider decreasing Minimum Element to Voxel Ratio)"
                        )
                        return 1
                    print("skipping scaling ", Scaling)
                    return 0
            else:

                mesh_file = File(os.environ['PATIENTDIR'] +
                                 '/CSF_ref/mesh_adapt_CSF' + str(Scaling) +
                                 '_old.xml.gz')
                mesh_file << mesh
                boundaries_file = File(os.environ['PATIENTDIR'] +
                                       '/CSF_ref/boundaries_adapt_CSF' +
                                       str(Scaling) + '_old.xml')
                subdomains_assigned_file = File(
                    os.environ['PATIENTDIR'] +
                    '/CSF_ref/subdomains_assigned_adapt_CSF' + str(Scaling) +
                    '_old.xml')
                boundaries_file << boundaries
                subdomains_assigned_file << subdomains_assigned

                mesh, boundaries, subdomains_assigned = mesh_refiner(
                    mesh, boundaries, subdomains_assigned, cell_ref, Domains,
                    cc_multicontact)

                if mesh.num_cells(
                ) > 10000000:  #users can adjust for their hardware
                    print(
                        "Mesh is too large, will have to check with bigger scaling"
                    )
                    csf_refined = -1
                    return csf_refined

    if loaded_from_h5 == 1:
        print("CSF_Subdomains_refinement file with scaling ", int(Scaling),
              " was loaded")
    else:
        if Field_calc_param.anisotropy == 1:
            subdomains = get_cellmap_tensors(mesh, subdomains_assigned,
                                             Domains, MRI_param, DTI_param,
                                             Field_calc_param.default_material)
        else:
            subdomains = get_cellmap(mesh, subdomains_assigned, Domains,
                                     MRI_param,
                                     Field_calc_param.default_material)

        print("CSF_Subdomains_refinement file with scaling ", int(Scaling),
              " was created")
        file = File(os.environ['PATIENTDIR'] +
                    '/CSF_ref/CSF_Subdomains_refinement_' + str(int(Scaling)) +
                    '.pvd')
        file << subdomains, mesh

    save_mesh_and_subdomains_to_h5(mesh, subdomains, subdomains_assigned,
                                   boundaries, Scaling)

    if cc_multicontact == True:
        Phi_r, Phi_im, Field_r, Field_im, max_E, J_r, J_im, j_dens_real, j_dens_im = compute_field_with_superposition(
            mesh, Domains, subdomains_assigned, subdomains, boundaries,
            Field_calc_param)
    else:
        Phi_r, Phi_im, Field_r, Field_im, max_E, J_r, J_im, j_dens_real, j_dens_im = get_field(
            mesh, Domains, subdomains, boundaries, Field_calc_param)

    if Scaling == 1:
        file = File(os.environ['PATIENTDIR'] + '/CSF_ref/Field_r_' +
                    str(Scaling) + '.pvd')
        file << Field_r
        print("CSF_Subdomains full refinement was created")
        file = File(os.environ['PATIENTDIR'] +
                    '/CSF_ref/CSF_Subdomains_full_ref.pvd')
        file << subdomains, mesh

        #import subprocess
        #subprocess.call('python Visualization_files/Paraview_CSFref.py', shell=True)

    Phi_amp_on_neuron = get_field_on_points(Phi_r, Phi_im,
                                            Field_calc_param.c_c, J_r, J_im)
    np.savetxt(os.environ['PATIENTDIR'] + '/CSF_ref/Field_on_points' +
               str(Scaling) + '.csv',
               Phi_amp_on_neuron,
               delimiter=" ")

    csf_refined = 1
    max_div = 0.0

    # define the absolute error threshold
    if Field_calc_param.c_c == True:
        if EQS_mode == 'EQS':
            #not the best approach, but both should be on the Dirichlet BCs
            max_phi_r = max(Phi_r.vector()[:])
            max_phi_im = max(Phi_im.vector()[:])

            min_phi_r = min(Phi_r.vector()[:])
            min_phi_im = min(Phi_im.vector()[:])

            phi_error = abs(
                (np.sqrt((max_phi_r - min_phi_r)**2 +
                         (max_phi_im - min_phi_im)**2)) * CSF_frac_div)
        else:
            phi_error = abs((max(Phi_r.vector()[:]) - min(Phi_r.vector()[:])) *
                            CSF_frac_div)  #should be scaled
    else:
        Phi_vector = [x for x in Domains.fi if x is not None]
        if Field_calc_param.external_grounding == True:
            Phi_vector.append(0.0)
        phi_error = abs(
            (max(Phi_vector) - min(Phi_vector)) * CSF_frac_div
        )  #Absolute potential error defined as a 1% of the maximum potential difference, VC case

    # compare solutions on the neuron compartments
    for inx in range(Phi_amp_on_neuron_old.shape[0]):
        if Best_scaling == 0:  #first iteration
            delim = abs(Phi_amp_on_neuron[inx, 3])
        else:
            delim = abs(Phi_amp_on_neuron_old[inx, 3])

        if max_div < abs(Phi_amp_on_neuron_old[inx, 3] -
                         Phi_amp_on_neuron[inx, 3]):
            max_div = abs(Phi_amp_on_neuron_old[inx, 3] -
                          Phi_amp_on_neuron[inx, 3])

        if max_div > phi_error:
            print("Deviation threshold: ", phi_error, "V")
            print("Deviation at least: ", max_div, "V")
            print("At point: ", Phi_amp_on_neuron_old[inx, 0],
                  Phi_amp_on_neuron_old[inx, 1], Phi_amp_on_neuron_old[inx, 2])
            print("Need further refinement of CSF")
            csf_refined = 0
            break

    if csf_refined == 1:
        mesh_file = File(os.environ['PATIENTDIR'] + '/CSF_ref/mesh_adapt_CSF' +
                         str(Scaling) + '.xml.gz')
        mesh_file << mesh
        boundaries_file = File(os.environ['PATIENTDIR'] +
                               '/CSF_ref/boundaries_adapt_CSF' + str(Scaling) +
                               '.xml')
        subdomains_assigned_file = File(
            os.environ['PATIENTDIR'] +
            '/CSF_ref/subdomains_assigned_adapt_CSF' + str(Scaling) + '.xml')
        boundaries_file << boundaries
        subdomains_assigned_file << subdomains_assigned

        print("Max. deviation: ", max_div, "V")
        print("Deviation threshold: ", phi_error, "V")
        print("CSF is refined enough")

    del voxel_array_CSF

    minutes = int((tim.clock() - start_CSF_refinement) / 60)
    secnds = int(tim.clock() - start_CSF_refinement) - minutes * 60
    print("----- CSF refinement iteration took ", minutes, " min ", secnds,
          " s -----\n")

    return csf_refined