def cal_geometry_pars_from_coors(self,domain,ref_ids,sorbate_ids):
        def _shift_in_unit_cell(coors):
            [x,y,z]=coors
            while x>5.038 or x<0:
                if x<0:
                    x=x+5.038
                elif x>5.038:
                    x=x-5.038
            while y>5.434 or y<0:
                if y<0:
                    y=y+5.434
                elif y>5.434:
                    y=y-5.434
            return np.array([x,y,z])

        basis=np.array([5.038,5.434,7.3707])
        ref_coors=[_shift_in_unit_cell(domain_creator.extract_coor(domain,ref_id)*basis) for ref_id in ref_ids]
        sorbate_coors=[_shift_in_unit_cell(domain_creator.extract_coor(domain,sorbate_id)*basis) for sorbate_id in sorbate_ids]
        y_shift=(sorbate_coors[0]+sorbate_coors[1]-ref_coors[0]-ref_coors[1])[1]/2./5.434
        v_shift=sorbate_coors[0][2]-ref_coors[0][2]
        r=f2(sorbate_coors[0],sorbate_coors[1])/2.
        vec_ref=np.array([1,0,0])
        vec_sorbate=sorbate_coors[1]-sorbate_coors[0]
        alpha=np.arccos(np.dot(vec_ref,vec_sorbate)/f2(vec_ref,np.array([0,0,0]))/f2(vec_sorbate,np.array([0,0,0])))/np.pi*180.
        return v_shift,alpha,y_shift
 def add_oxygen_pair_muscovite(self,domain,ref_id,O_ids,v_shift,basis=np.array([5.038,5.434,7.3707])):
 #v_shift and r are in unit of angstrom, and phi in degree
 #use coordinates during fitting rather than freezing the ref to the bulk position
     alpha=60.0605#specifically for muscovite
     r=5.208335#specifically for muscovite
     ref_point=None
     if len(ref_id)==1:
         ref_point=domain_creator.extract_coor(domain,ref_id)*basis+[0,0,v_shift]
     if len(ref_id)==2:
         ref_point1=domain_creator.extract_coor(domain,ref_id[0])*basis
         ref_point2=domain_creator.extract_coor(domain,ref_id[1])*basis
         ref_point=(ref_point1+ref_point2)/2+[0,0,v_shift]
     x_shift=r*np.cos(alpha/180*np.pi)
     y_shift=r*np.sin(alpha/180*np.pi)
     point1=np.array([ref_point[0]-x_shift,ref_point[1]-y_shift,ref_point[2]])/basis
     point2=np.array([ref_point[0]+x_shift,ref_point[1]+y_shift,ref_point[2]])/basis
     O_index1=None
     O_index2=None
     try:
         O_index1=np.where(domain.id==O_ids[0])[0][0]
         O_index2=np.where(domain.id==O_ids[1])[0][0]
     except:
         domain.add_atom( O_ids[0], "O",  point1[0] ,point1[1], point1[2] ,4.,     1.00000e+00 ,     1.00000e+00 )
         domain.add_atom( O_ids[1], "O",  point2[0] ,point2[1], point2[2] ,4.,     1.00000e+00 ,     1.00000e+00 )
     if O_index1!=None:
         domain.x[O_index1],domain.y[O_index1],domain.z[O_index1]=point1[0],point1[1],point1[2]
         domain.x[O_index2],domain.y[O_index2],domain.z[O_index2]=point2[0],point2[1],point2[2]
     return np.append([point1],[point2],axis=0)
 def add_single_oxygen(self,domain,ref_id,O_id,v_shift):
 #v_shift and r are in unit of angstrom
 #use coordinates during fitting rather than freezing the ref to the bulk position
 #here only add one water molecule each time (not a couple), so dont need r and alpha
     basis=np.array([5.038,5.434,7.3707])
     ref_point=None
     if len(ref_id)==1:
         ref_point=(domain_creator.extract_coor(domain,ref_id)*basis+[0,0,v_shift])/basis
     if len(ref_id)==2:
         ref_point1=domain_creator.extract_coor(domain,ref_id[0])*basis
         ref_point2=domain_creator.extract_coor(domain,ref_id[1])*basis
         ref_point=((ref_point1+ref_point2)/2+[0,0,v_shift])/basis
     O_index=None
     try:
         O_index=np.where(domain.id==O_id)[0][0]
     except:
         domain.add_atom( O_id, "O",  ref_point[0] ,ref_point[1], ref_point[2] ,4.,     1.00000e+00 ,     1.00000e+00 )
     if O_index!=None:
         domain.x[O_index],domain.y[O_index],domain.z[O_index]=ref_point[0],ref_point[1],ref_point[2]
     return np.array([ref_point])