示例#1
0
def build_hamiltonian(defect_list,principal_layer,path,system_type):

  # finding out the list of distinct defects
  distinct_defects = []
  for defect in defect_list:
    if defect not in distinct_defects:
      distinct_defects.append(defect)

  # now we will load the matrices of the needed distinct defects
  # and gather them in a dictionnary. Also we will extract the matrix
  # sizes
  hamiltonian_matrices     = {}
  hamiltonian_matrix_sizes = {}
  for defect in distinct_defects:
    filename = ""
    for string in os.listdir(path+"/"+defect):
      if '_htC.dat' in string:
        filename = string
    conductor_matrix = read_htC(path+"/"+defect+"/"+filename)
    hamiltonian_matrices[defect]     = conductor_matrix
    hamiltonian_matrix_sizes[defect] = conductor_matrix.shape[0]

  # loading the H00 and H01 matrices of the lead
  filename = ""
  for string in os.listdir(path+"/"+principal_layer):
    if '_htC.dat' in string:
      filename = string
  (h00_matrix,h01_matrix) = read_lead(path+"/"+principal_layer+"/"+filename)
  h00_size = h00_matrix.shape[0]
  h01_size = h01_matrix.shape[0]
  hamiltonian_matrices[principal_layer]     = (h00_matrix,h01_matrix)
  hamiltonian_matrix_sizes[principal_layer] = (h00_size,h01_size)

  # determining the nbandc parameter
  H_sizes = []
  for defect in hamiltonian_matrix_sizes.keys():
    if defect!=principal_layer:
      H_sizes.append(hamiltonian_matrix_sizes[defect]+1)
  H_sizes.append(h00_size+h01_size)
  nbandc = max(H_sizes)

  # asking the user for the number of unit cells per principal layer
  try:
    num_cell_in_pl = int( raw_input('\n how many unit cells in one principal layer : ') )
  except:
    print ""
    print " Error in system_builder :"
    print " the program could not convert the number of unit"
    print " cells into an integer"
    print " Exiting the program..."
    print ""
    sys.exit(1)
  num_wf_in_cell = h00_size / num_cell_in_pl # a small check
  if num_cell_in_pl*num_wf_in_cell!=h00_size:
    print ""
    print " Error in system_builder :"
    print " The number of unit cells in a principal layer "
    print " multiplied by the number of Wannier Functions "
    print " per cell does not add up to the number of WFs "
    print " in  a principal layer. You probably entered a "
    print " wrong number of unit cells.                   "
    print " Exiting the program...                        "
    print ""
    sys.exit(1)

  # asking the user about the number of buffer unit cells to
  # "squeeze in" between the defects in the system
  try:
    buffer_num = int( raw_input('\n how many buffer unit cells between defects : ') )
  except:
    print ""
    print " Error in system_builder :"
    print " the program could not convert the number of buffer"
    print " unit cells into an integer"
    print " Exiting the program..."
    print ""
    sys.exit(1)

  # size of the final Hamiltonian matrix
  total_size = 2*h00_size
  for defect in defect_list:
    if defect==principal_layer:
      total_size += h00_size
    else:
      total_size += hamiltonian_matrix_sizes[defect]
  total_size += len(defect_list)*num_wf_in_cell*buffer_num

  ### it is now time to build the final matrix ###
  from math import ceil

  # starting with a zero matrix with the right size
  dis_matrix = numpy.zeros((total_size,total_size),dtype='float')

  # updating the defect list by adding one principal layer at
  # the beginning of the structure and one at the end. This ensures
  # a clean connection with the leads.
  defect_list = [principal_layer]+defect_list+[principal_layer]

  # Main loop over the defect index
  offset = 0 # this parameter is used in the loop as a reference point
  for i in xrange(len(defect_list)):
    # Starting by inserting the defect matrices with their "left"
    # padding. Special attention is to be taken for the very first
    # and the very last defects that correspond to the beginning and
    # terminating lead principal layers
    if i==0 or i==len(defect_list)-1:
      dis_matrix[offset:offset+h00_size,offset:offset+h00_size] = hamiltonian_matrices[principal_layer][0]
      offset += h00_size
    else:
      # inserting the padding matrix first
      if defect_list[i]==principal_layer:
        def_size   = h00_size
        def_matrix = hamiltonian_matrices[principal_layer][0]
        num_cell   = int( buffer_num + num_cell_in_pl )
      else:
        def_size   = hamiltonian_matrix_sizes[defect_list[i]]
        def_matrix = hamiltonian_matrices[defect_list[i]]
        num_cell   = int( buffer_num + float(def_size)/(2.0*num_wf_in_cell) )
      if buffer_num >= 1:
        num_pl       = int( ceil(float(num_cell) / float(num_cell_in_pl)) )
        dummy_matrix = build_pristine( num_pl,
                                       hamiltonian_matrices[principal_layer][0],
                                       hamiltonian_matrices[principal_layer][1] )
        dis_matrix[offset:offset+num_cell*num_wf_in_cell,offset:offset+num_cell*num_wf_in_cell] = \
        dummy_matrix[:num_cell*num_wf_in_cell,:num_cell*num_wf_in_cell]
      # then inserting the defect matrix itself
      dis_matrix[offset+buffer_num*num_wf_in_cell:offset+buffer_num*num_wf_in_cell+def_size,
                 offset+buffer_num*num_wf_in_cell:offset+buffer_num*num_wf_in_cell+def_size] = def_matrix
      offset += buffer_num*num_wf_in_cell+def_size
    # Now we have to connect the defects together (off-diagonal elements)
    # We exclude the last defect since this one is not connected with any
    # other defect "to the right"
    if i <= len(defect_list)-2:
      if defect_list[i]==principal_layer:
        def_size_a   = h00_size
        def_matrix_a = hamiltonian_matrices[principal_layer][0]
      else:
        def_size_a   = hamiltonian_matrix_sizes[defect_list[i]]
        def_matrix_a = hamiltonian_matrices[defect_list[i]]
      if defect_list[i+1]==principal_layer:
        def_size_b   = h00_size
        def_matrix_b = hamiltonian_matrices[principal_layer][0]
      else:
        def_size_b   = hamiltonian_matrix_sizes[defect_list[i+1]]
        def_matrix_b = hamiltonian_matrices[defect_list[i+1]]
      # if both the current defect and the next one are principal layers, we 
      # insert simply H01 as a connection matrix
      if defect_list[i]==principal_layer and defect_list[i+1]==principal_layer:  
        dis_matrix[offset-h00_size:offset,offset:offset+h00_size] = hamiltonian_matrices[principal_layer][1]
        dis_matrix[offset:offset+h00_size,offset-h00_size:offset] = numpy.transpose(hamiltonian_matrices[principal_layer][1])
      # case where the current defect is a principal layer
      elif defect_list[i]==principal_layer:
        num_cell_a = num_cell_in_pl
        num_cell_b = int( buffer_num + float(def_size_b)/(2.0*num_wf_in_cell) )
        if num_cell_b==0:
          num_cell_b = int( buffer_num + ceil(float(def_size_b)/(2.0*num_wf_in_cell)) )
        num_cell_c = min(num_cell_a,num_cell_b)
        if num_cell_c >= num_cell_in_pl:
          dis_matrix[offset-h00_size:offset,offset:offset+h00_size] = hamiltonian_matrices[principal_layer][1]
          dis_matrix[offset:offset+h00_size,offset-h00_size:offset] = numpy.transpose(hamiltonian_matrices[principal_layer][1])
        else:
          dis_matrix[offset-num_cell_c*num_wf_in_cell:offset,offset:offset+num_cell_c*num_wf_in_cell] = \
                          hamiltonian_matrices[principal_layer][1][h00_size-num_cell_c*num_wf_in_cell:,:num_cell_c*num_wf_in_cell]
          dis_matrix[offset:offset+num_cell_c*num_wf_in_cell,offset-num_cell_c*num_wf_in_cell:offset] = \
                          numpy.transpose(hamiltonian_matrices[principal_layer][1][h00_size-num_cell_c*num_wf_in_cell:,:num_cell_c*num_wf_in_cell])
      # case where the next defect is a principal layer
      elif defect_list[i+1]==principal_layer:
        num_cell_b = num_cell_in_pl + buffer_num
        num_cell_a = int( float(def_size_a)/(2.0*num_wf_in_cell) )
        if num_cell_a==0:
          num_cell_a = int( ceil(float(def_size_a)/(2.0*num_wf_in_cell)) )
        num_cell_c = min(num_cell_a,num_cell_b)
        if num_cell_c >= num_cell_in_pl:
          dis_matrix[offset-h00_size:offset,offset:offset+h00_size] = hamiltonian_matrices[principal_layer][1]
          dis_matrix[offset:offset+h00_size,offset-h00_size:offset] = numpy.transpose(hamiltonian_matrices[principal_layer][1])
        else:
          dis_matrix[offset-num_cell_c*num_wf_in_cell:offset,offset:offset+num_cell_c*num_wf_in_cell] = \
                          hamiltonian_matrices[principal_layer][1][h00_size-num_cell_c*num_wf_in_cell:,:num_cell_c*num_wf_in_cell]
          dis_matrix[offset:offset+num_cell_c*num_wf_in_cell,offset-num_cell_c*num_wf_in_cell:offset] = \
                          numpy.transpose(hamiltonian_matrices[principal_layer][1][h00_size-num_cell_c*num_wf_in_cell:,:num_cell_c*num_wf_in_cell])
      # case where both the current and the next defect are not principal layers
      else:
        num_cell_a = int( float(def_size_a)/(2.0*num_wf_in_cell) )
        if num_cell_a==0:
          num_cell_a = int( ceil(float(def_size_a)/(2.0*num_wf_in_cell)) )
        num_cell_b = int( buffer_num + float(def_size_b)/(2.0*num_wf_in_cell) )
        if num_cell_b==0:
          num_cell_b = int( buffer_num + ceil(float(def_size_b)/(2.0*num_wf_in_cell)) )
        num_cell_c = min(num_cell_a,num_cell_b)
        if num_cell_c >= num_cell_in_pl:
          dis_matrix[offset-h00_size:offset,offset:offset+h00_size] = hamiltonian_matrices[principal_layer][1]
          dis_matrix[offset:offset+h00_size,offset-h00_size:offset] = numpy.transpose(hamiltonian_matrices[principal_layer][1])
        else:
          dis_matrix[offset-num_cell_c*num_wf_in_cell:offset,offset:offset+num_cell_c*num_wf_in_cell] = \
                          hamiltonian_matrices[principal_layer][1][h00_size-num_cell_c*num_wf_in_cell:,:num_cell_c*num_wf_in_cell]
          dis_matrix[offset:offset+num_cell_c*num_wf_in_cell,offset-num_cell_c*num_wf_in_cell:offset] = \
                          numpy.transpose(hamiltonian_matrices[principal_layer][1][h00_size-num_cell_c*num_wf_in_cell:,:num_cell_c*num_wf_in_cell])

  # writing the system's Hamiltonian matrix to file
  write_htC("%s_system_htC.dat" %("./"+system_type),dis_matrix)

  # creating the final directory
  os.system("rm -rf %s_system/" %(system_type))
  os.mkdir("%s_system" %(system_type))
  os.system("mv %s_system_htC.dat %s_system/." %(system_type,system_type))

  # adding the H_L, H_LC and H_CR matrices
  hl_file = open("./%s_system/%s_system_htL.dat" %(system_type,system_type),'w')
  hl_file.write(' # Left lead matrix with H00 and H01 \n')
  hl_file.write(' %6i \n' %(h00_size,))
  for j in xrange(h00_size):
    for i in xrange(h00_size):
      hl_file.write(' %10.6f' %(hamiltonian_matrices[principal_layer][0][i,j],))
    hl_file.write(' \n')
  hl_file.write(' %6i \n' %(h01_size,))
  for j in xrange(h01_size):
    for i in xrange(h01_size):
      hl_file.write(' %10.6f' %(hamiltonian_matrices[principal_layer][1][i,j],))
    hl_file.write(' \n')
  hl_file.close()
  hlc_file = open("./%s_system/%s_system_htLC.dat" %(system_type,system_type),'w')
  hlc_file.write(' # Left lead - Conductor matrix H_LC \n')
  hlc_file.write(' %6i  %6i \n' %(h01_size,h01_size))
  for j in xrange(h01_size):
    for i in xrange(h01_size):
      hlc_file.write(' %10.6f' %(hamiltonian_matrices[principal_layer][1][i,j],))
    hlc_file.write(' \n')
  hlc_file.close()
  hcr_file = open("./%s_system/%s_system_htCR.dat" %(system_type,system_type),'w')
  hcr_file.write(' # Conductor - Right lead matrix H_CR \n')
  hcr_file.write(' %6i  %6i \n' %(h01_size,h01_size))
  for j in xrange(h01_size):
    for i in xrange(h01_size):
      hcr_file.write(' %10.6f' %(hamiltonian_matrices[principal_layer][1][i,j],))
    hcr_file.write(' \n')
  hcr_file.close()

  # At last the Wannier90 master input file
  w90_input = open("./%s_system/%s_system.win" %(system_type,system_type),'w')
  w90_input.write("# %s system with %6i defect(s) \n" %(system_type,len(defect_list)-2,))
  w90_input.write("# written by 'system_builder.py' on %s at %s \n" %(time.strftime("%A, %d %B %Y",time.localtime()),
                                                                      time.strftime("%H:%M:%S",time.localtime())))
  w90_input.write("\n")
  w90_input.write("transport          = .true. \n")
  w90_input.write("transport_mode     =  lcr   \n")
  w90_input.write("tran_read_ht       = .true. \n")
  w90_input.write("tran_use_same_lead = .true. \n")
  w90_input.write("tran_win_min       = -3.0   \n")
  w90_input.write("tran_win_max       =  2.0   \n")
  w90_input.write("tran_energy_step   =  0.01  \n")
  w90_input.write("tran_num_ll        = %6i \n" %(h00_size,))
  w90_input.write("tran_num_rr        = %6i \n" %(h00_size,))
  w90_input.write("tran_num_cc        = %6i \n" %(total_size,))
  w90_input.write("tran_num_lc        = %6i \n" %(h00_size,))
  w90_input.write("tran_num_cr        = %6i \n" %(h00_size,))
  w90_input.write("tran_num_bandc     = %6i \n" %(nbandc,))
  w90_input.close()

  return (num_cell_in_pl,buffer_num)
示例#2
0
def main_routine(wf_total,
                 wf_per_pl,
                 cells_per_pl,
                 cond_dir,
                 wannier_functions,
                 atom_number,
                 atomic_coordinates,
                 hamiltonian_matrix,
                 print_atomic_coordinates,
                 print_all_permutations):

  from math import floor
  import os

  # asking the user how many unit cells on the left are to be removed
  try:
    left_cells  = int(raw_input("\n Number of left  cells to remove in the conductor : "))
    right_cells = int(raw_input("\n Number of right cells to remove in the conductor : "))
    print ""
  except:
    print ""
    print " Error in cut_conductor :"
    print " Could not transform the number of cells into"
    print " an integer"
    print " Exiting the program..."
    print ""
    sys.exit(1)

  # checking that some of the information in the *_tran_info.dat file
  # is actually compatible with some of the information about the matrix
  if wf_total-2*wf_per_pl!=hamiltonian_matrix.shape[0]:
    print ""
    print " Error in cut_conductor :"
    print " the number of Wannier Functions in the conductor"
    print " region is incompatible."
    print " In file *_tran_info.dat, this number is : %6i" %(wf_total-2*wf_per_pl)
    print " In the matrix file, this number is      : %6i" %(hamiltonian_matrix.shape[0])
    print " Exiting the program..."
    print ""
    sys.exit(1)

  # checking whether the number of cells are not too big
  num_wann_per_cell = int(wf_per_pl/cells_per_pl)
  max_cell_number = int(floor(hamiltonian_matrix.shape[0]/(2.0*num_wann_per_cell)))
  user_continue = "dummy"
  if left_cells > max_cell_number or right_cells > max_cell_number:
    print ""
    print " Warning in cut_conductor :"
    print " The number of unit cells to remove seems too big."
    print " The program expects at most %i to be removed on " %(max_cell_number)
    print " one side (for systems with the defect 'in the middle')"
    print " Do you still want to continue ?"
    while user_continue not in ['yes','no']:
      user_continue = str(raw_input("\n -> type 'yes' or 'no' : "))
  if user_continue=='no':
    print " Exiting the program..."
    print ""
    sys.exit(1)

  # asking the user the number of atoms per unit cell
  if print_atomic_coordinates:
    try:
      atoms_per_cell = int(raw_input(" How many atoms in the lead unit cell : "))
      print ""
    except:
      print ""
      print " Error in cut_conductor :"
      print " Could not transform the number of atoms per cell"
      print " into an integer"
      print " Exiting the program..."
      print ""
      sys.exit(1)

  # constructing the matrix and the atomic position files
  if not print_all_permutations:
    # creating a directory for storing the reduced matrix and
    # possibly the atomic coodinates
    os.mkdir("./%i_left_%i_right" %(left_cells,right_cells))
    # first we construct the reduced matrix
    final_matrix = hamiltonian_matrix[left_cells*num_wann_per_cell:hamiltonian_matrix.shape[0]-right_cells*num_wann_per_cell,
                                      left_cells*num_wann_per_cell:hamiltonian_matrix.shape[0]-right_cells*num_wann_per_cell]
    write_htC("./%i_left_%i_right/%i_left_%i_right_htC.dat" %(left_cells,
                                                              right_cells,
                                                              left_cells,
                                                              right_cells),final_matrix)
    # then optionnaly the atomic positions
    if print_atomic_coordinates:
      # computing the size of the reduced structure
      if cond_dir=='x':
        conductor_size = atomic_coordinates[-(cells_per_pl+right_cells)*atoms_per_cell].x - \
                         atomic_coordinates[(cells_per_pl+left_cells)*atoms_per_cell].x
      elif cond_dir=='y':
        conductor_size = atomic_coordinates[-(cells_per_pl+right_cells)*atoms_per_cell].y - \
                         atomic_coordinates[(cells_per_pl+left_cells)*atoms_per_cell].y
      else:
        conductor_size = atomic_coordinates[-(cells_per_pl+right_cells)*atoms_per_cell].z - \
                         atomic_coordinates[(cells_per_pl+left_cells)*atoms_per_cell].z
      # selecting the atoms in the reduced structure
      final_positions = atomic_coordinates[(cells_per_pl+left_cells)*atoms_per_cell:len(atomic_coordinates)-(cells_per_pl+right_cells)*atoms_per_cell]
      # translating the coordinates in the direction of conduction such
      # that the left-most atom is at 0
      final_positions = translate_to_zero(final_positions,cond_dir)
      # writing the positions to an xyz file
      write_xyz("./%i_left_%i_right/%i_left_%i_right.xyz" %(left_cells,
                                                            right_cells,
                                                            left_cells,
                                                            right_cells),final_positions,conductor_size)
  else:
    # here we do the same thing as above but for all possible cutting schemes
    for i in xrange(left_cells+1):
      for j in xrange(right_cells+1):
        # creating a directory for storing the reduced matrix and
        # possibly the atomic coodinates
        os.mkdir("./%i_left_%i_right" %(i,j))
        # first we construct the reduced matrix
        final_matrix = hamiltonian_matrix[i*num_wann_per_cell:hamiltonian_matrix.shape[0]-j*num_wann_per_cell,
                                          i*num_wann_per_cell:hamiltonian_matrix.shape[0]-j*num_wann_per_cell]
        write_htC("./%i_left_%i_right/%i_left_%i_right_htC.dat" %(i,j,i,j),final_matrix)
        # then optionnaly the atomic positions
        if print_atomic_coordinates:
          # computing the size of the reduced structure
          if cond_dir=='x':
            conductor_size = atomic_coordinates[-(cells_per_pl+j)*atoms_per_cell].x - \
                             atomic_coordinates[(cells_per_pl+i)*atoms_per_cell].x
          elif cond_dir=='y':
            conductor_size = atomic_coordinates[-(cells_per_pl+j)*atoms_per_cell].y - \
                             atomic_coordinates[(cells_per_pl+i)*atoms_per_cell].y
          else:
            conductor_size = atomic_coordinates[-(cells_per_pl+j)*atoms_per_cell].z - \
                             atomic_coordinates[(cells_per_pl+i)*atoms_per_cell].z
          # selecting the atoms in the reduced structure
          final_positions = atomic_coordinates[(cells_per_pl+i)*atoms_per_cell:len(atomic_coordinates)-(cells_per_pl+j)*atoms_per_cell]
          # translating the coordinates in the direction of conduction such
          # that the left-most atom is at 0
          final_positions = translate_to_zero(final_positions,cond_dir)
          # writing the positions to an xyz file
          write_xyz("./%i_left_%i_right/%i_left_%i_right.xyz" %(i,j,i,j),final_positions,conductor_size)

  # At last a simple Warning to the user for checking the atomic position files
  if print_atomic_coordinates: 
    print ""
    print " WARNING :"
    print " In constructing the atomic position files, this program uses a"
    print " very simple sorting algorithm. Please visualize the structures"
    print " yourself in order to double check them."

  return
示例#3
0
def main_routine(wf_total,
                 wf_per_pl,
                 cells_per_pl,
                 cond_dir,
                 second_dir,
                 wannier_functions,
                 atom_number,
                 atomic_coordinates,
                 hamiltonian_matrix):

  # making sure the user properly tuned the constraints function
  print ""
  print " Did you modify the 'constraints.py' module"
  print " to fit your system ?"
  constraints_modified = 'dummy'
  while constraints_modified not in ['yes','no']:
    constraints_modified = str(raw_input("\n -> type 'yes' or 'no' : "))
  if constraints_modified=='no':
    print ""
    sys.exit(1)
  print ""

  # checking that some of the information in the *_tran_info.dat file
  # is actually compatible with some of the information about the matrix
  if wf_total-2*wf_per_pl!=hamiltonian_matrix.shape[0]:
    print ""
    print " Error in compactify_conductor :"
    print " the number of Wannier Functions in the conductor"
    print " region is incompatible."
    print " In file *_tran_info.dat, this number is : %6i" %(wf_total-2*wf_per_pl)
    print " In the matrix file, this number is      : %6i" %(hamiltonian_matrix.shape[0])
    print " Exiting the program..."
    print ""
    sys.exit(1)

  # creating two lists of indices. One for the backbone WF and one for
  # the defect WF. Those lists contain the indices of the WF
  backbone_list = []
  defect_list   = []
  for i in xrange(wf_per_pl,wf_total-wf_per_pl):  # this loop restricts to the WF in the
                                                  # conductor region
    if constraints(wannier_functions[i].x,wannier_functions[i].y,wannier_functions[i].z):
      backbone_list.append(i-wf_per_pl)
    else:
      defect_list.append(i-wf_per_pl)

  # now we will re-order the Wannier Function basis in such a way that
  # the defect Wannier Functions will be "in the middle"
  middle_point = len(backbone_list)/2
  final_list = backbone_list[:middle_point] + defect_list + backbone_list[middle_point:]

  # all we have to do now is re-construct the hamiltonian matrix with
  # this newly ordered basis
  reordered_hamiltonian_matrix = numpy.zeros((hamiltonian_matrix.shape[0],
                                              hamiltonian_matrix.shape[1]),dtype='float')
  for row in xrange(len(final_list)):
    for col in xrange(len(final_list)):
      reordered_hamiltonian_matrix[row,col] = hamiltonian_matrix[final_list[row],final_list[col]]

  # writing the new hamiltonian to a Wannier90 compatible file
  write_htC("compactified_htC.dat",reordered_hamiltonian_matrix)

  # generating the new *_tran_info.dat file
  PL1       = wannier_functions[:wf_per_pl]
  conductor = wannier_functions[wf_per_pl:-wf_per_pl]
  PL4       = wannier_functions[-wf_per_pl:]
  final_conductor = []
  for index in final_list:
    final_conductor.append(conductor[index])
  final_wf_list = PL1 + final_conductor + PL4
  
  write_tran_info(wf_total,
                  wf_per_pl,
                  cells_per_pl,
                  cond_dir,
                  second_dir,
                  final_wf_list,
                  atom_number,
                  atomic_coordinates)

  return
示例#4
0
def main_routine(wf_total,
                 wf_per_pl,
                 cells_per_pl,
                 cond_dir,
                 second_dir,
                 wannier_functions,
                 atom_number,
                 atomic_coordinates,
                 matrix,
                 angle,
                 delta):

  # first we separate the left-most principal layer, the conductor region
  # and the right-most principal layer
  PL1       = wannier_functions[:wf_per_pl]
  conductor = wannier_functions[wf_per_pl:-wf_per_pl]
  PL4       = wannier_functions[-wf_per_pl:]

  # now we compute the unit vector for the axis of rotation
  point_A = barycenter(PL1)
  point_B = barycenter(PL4)
  unit_vector = (1.0/numpy.linalg.norm(point_B-point_A))*(point_B-point_A)
  if cond_dir=='x':
    reference = numpy.array([1.0,0.0,0.0])
  elif cond_dir=='y':
    reference = numpy.array([0.0,1.0,0.0])
  else:
    reference = numpy.array([0.0,0.0,1.0])
  if numpy.dot(unit_vector,reference)<=0.95:
    print ""
    print " Warning in rotate_conductor :"
    print " The  computed  unit  vector for the axis of"
    print " rotation seems to be off from the reference"
    print " unit vector : %s" %(cond_dir)
    print " The dot product of unit vector with %s is : %3.2f" %(cond_dir,numpy.dot(unit_vector,reference))
    print ""
    user_answer = ""
    while user_answer not in ["yes", "no"]:
      user_answer = str(raw_input(" is this OK ? ('yes' or 'no') "))
    if user_answer=='no':
      print " Exiting the program..."
      print ""
      sys.exit(1)

  # we search the groups of WF with similar centres. To do this
  # a group is identified by the index of the first WF in the group
  # and the group size
  gp_dict = {}
  gp_bool = numpy.zeros(len(conductor),dtype='bool')
  for i in xrange(len(conductor)):
    if gp_bool[i]==False:
      gp_bool[i] = True
      gp_size    = 1
      # for each wf we search for similar centres just around that wf
      for j in xrange(max(i-10,0),min(i+11,len(conductor))):
        if gp_bool[j]==False:
          if same_center(conductor[i],conductor[j]):
            gp_bool[j] = True
            gp_size   += 1
      # if gp_size is at least 2 we add this group to the dictionnary
      if gp_size >= 2:
        gp_dict[conductor[i].index] = gp_size

  # now we need to remove the redondant WF from the conductor
  not_to_add = []
  for wf in conductor:
    if wf.index in gp_dict.keys():
      for j in xrange(1,gp_dict[wf.index]):
        not_to_add.append(wf.index+j)
  reduced_conductor = []
  for wf in conductor:
    if wf.index not in not_to_add:
      reduced_conductor.append(wf)

  # with the reduced_conductor list, we can rotate the centers
  reduced_rotated_conductor = rotate_wf(reduced_conductor,angle,unit_vector,point_A)

  # we then sort the rotated Wannier Functions
  sorted_reduced_conductor = sort(reduced_rotated_conductor,
                                  cond_dir,
                                  second_dir,
                                  delta)

  # we re-insert the WF with similar centers
  sorted_conductor = []
  for wf in sorted_reduced_conductor:
    if wf.index not in gp_dict.keys():
      sorted_conductor.append(wf)
    else:
      sorted_conductor.append(wf)
      for j in xrange(1,gp_dict[wf.index]):
        new_wf = wannier_function()
        pos_in_list = wf.index+j-conductor[0].index
        new_wf.setindex(conductor[pos_in_list].index)
        new_wf.setx(wf.x)
        new_wf.sety(wf.y)
        new_wf.setz(wf.z)
        new_wf.setonsite(conductor[pos_in_list].onsite)
        sorted_conductor.append(new_wf)

  # we now find the mapping between the original order of WF
  # and the final order after sorting
  final_order = []
  reference   = conductor[0].index
  for wf in sorted_conductor:
    final_order.append(wf.index-reference)

  # now we can reconstruct the matrix
  final_matrix = numpy.zeros((matrix.shape[0],matrix.shape[1]),dtype='float')
  for i in xrange(matrix.shape[0]):
    for j in xrange(matrix.shape[1]):
      final_matrix[i,j] = matrix[final_order[i],final_order[j]]
  write_htC('rotated_matrix_htC.dat',final_matrix)

  # at last we re-generate the *_tran_info.dat file
  final_wf_list = PL1 + sorted_conductor + PL4
  final_atomic_coordinates = rotate_atoms(atomic_coordinates,angle,unit_vector,point_A)
  write_tran_info(wf_total,
                  wf_per_pl,
                  cells_per_pl,
                  cond_dir,
                  second_dir,
                  final_wf_list,
                  atom_number,
                  final_atomic_coordinates)

  return