Beispiel #1
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
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
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