def trans_rdm12s(cibra, ciket, norb, nelec, link_index=None, reorder=True): r'''Spin separated 1- and 2-particle transition density matrices. The return values include two lists, a list of 1-particle transition density matrices and a list of 2-particle transition density matrices. The density matrices are: (alpha,alpha), (beta,beta) for 1-particle transition density matrices; (alpha,alpha,alpha,alpha), (alpha,alpha,beta,beta), (beta,beta,alpha,alpha), (beta,beta,beta,beta) for 2-particle transition density matrices. 1pdm[p,q] = :math:`\langle q^\dagger p\rangle`; 2pdm[p,q,r,s] = :math:`\langle p^\dagger r^\dagger s q\rangle`. ''' dm1a, dm2aa = rdm.make_rdm12_spin1('FCItdm12kern_a', cibra, ciket, norb, nelec, link_index, 2) dm1b, dm2bb = rdm.make_rdm12_spin1('FCItdm12kern_b', cibra, ciket, norb, nelec, link_index, 2) _, dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', cibra, ciket, norb, nelec, link_index, 0) _, dm2ba = rdm.make_rdm12_spin1('FCItdm12kern_ab', ciket, cibra, norb, nelec, link_index, 0) dm2ba = dm2ba.transpose(3,2,1,0) if reorder: dm1a, dm2aa = rdm.reorder_rdm(dm1a, dm2aa, inplace=True) dm1b, dm2bb = rdm.reorder_rdm(dm1b, dm2bb, inplace=True) return (dm1a, dm1b), (dm2aa, dm2ab, dm2ba, dm2bb)
def make_rdm12s(fcivec, norb, nelec, link_index=None, reorder=True): r'''Spin separated 1- and 2-particle density matrices. The return values include two lists, a list of 1-particle density matrices and a list of 2-particle density matrices. The density matrices are: (alpha,alpha), (beta,beta) for 1-particle density matrices; (alpha,alpha,alpha,alpha), (alpha,alpha,beta,beta), (beta,beta,beta,beta) for 2-particle density matrices. 1pdm[p,q] = :math:`\langle q^\dagger p\rangle`; 2pdm[p,q,r,s] = :math:`\langle p^\dagger r^\dagger s q\rangle`. Energy should be computed as E = einsum('pq,qp', h1, 1pdm) + 1/2 * einsum('pqrs,pqrs', eri, 2pdm) where h1[p,q] = <p|h|q> and eri[p,q,r,s] = (pq|rs) ''' dm1a, dm2aa = rdm.make_rdm12_spin1('FCIrdm12kern_a', fcivec, fcivec, norb, nelec, link_index, 1) dm1b, dm2bb = rdm.make_rdm12_spin1('FCIrdm12kern_b', fcivec, fcivec, norb, nelec, link_index, 1) _, dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', fcivec, fcivec, norb, nelec, link_index, 0) if reorder: dm1a, dm2aa = rdm.reorder_rdm(dm1a, dm2aa, inplace=True) dm1b, dm2bb = rdm.reorder_rdm(dm1b, dm2bb, inplace=True) return (dm1a, dm1b), (dm2aa, dm2ab, dm2bb)
def trans_rdm12s(cibra, ciket, norb, nelec, link_index=None, reorder=True): r'''Spin separated 1- and 2-particle transition density matrices. The return values include two lists, a list of 1-particle transition density matrices and a list of 2-particle transition density matrices. The density matrices are: (alpha,alpha), (beta,beta) for 1-particle transition density matrices; (alpha,alpha,alpha,alpha), (alpha,alpha,beta,beta), (beta,beta,alpha,alpha), (beta,beta,beta,beta) for 2-particle transition density matrices. 1pdm[p,q] = :math:`\langle q^\dagger p\rangle`; 2pdm[p,q,r,s] = :math:`\langle p^\dagger r^\dagger s q\rangle`. ''' dm1a, dm2aa = rdm.make_rdm12_spin1('FCItdm12kern_a', cibra, ciket, norb, nelec, link_index, 2) dm1b, dm2bb = rdm.make_rdm12_spin1('FCItdm12kern_b', cibra, ciket, norb, nelec, link_index, 2) _, dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', cibra, ciket, norb, nelec, link_index, 0) _, dm2ba = rdm.make_rdm12_spin1('FCItdm12kern_ab', ciket, cibra, norb, nelec, link_index, 0) dm2ba = dm2ba.transpose(3, 2, 1, 0) if reorder: dm1a, dm2aa = rdm.reorder_rdm(dm1a, dm2aa, inplace=True) dm1b, dm2bb = rdm.reorder_rdm(dm1b, dm2bb, inplace=True) return (dm1a, dm1b), (dm2aa, dm2ab, dm2ba, dm2bb)
def make_rdm12s(fcivec, norb, nelec, link_index=None, reorder=True): dm1a, dm2aa = rdm.make_rdm12_spin1('FCIrdm12kern_a', fcivec, fcivec, norb, nelec, link_index, 1) dm1b, dm2bb = rdm.make_rdm12_spin1('FCIrdm12kern_b', fcivec, fcivec, norb, nelec, link_index, 1) _, dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', fcivec, fcivec, norb, nelec, link_index, 0) if reorder: dm1a, dm2aa = rdm.reorder_rdm(dm1a, dm2aa, inplace=True) dm1b, dm2bb = rdm.reorder_rdm(dm1b, dm2bb, inplace=True) return (dm1a, dm1b), (dm2aa, dm2ab, dm2bb)
def trans_rdm12s(cibra, ciket, norb, nelec, link_index=None, reorder=True): dm1a, dm2aa = rdm.make_rdm12_spin1('FCItdm12kern_a', cibra, ciket, norb, nelec, link_index, 2) dm1b, dm2bb = rdm.make_rdm12_spin1('FCItdm12kern_b', cibra, ciket, norb, nelec, link_index, 2) _, dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', cibra, ciket, norb, nelec, link_index, 0) _, dm2ba = rdm.make_rdm12_spin1('FCItdm12kern_ab', ciket, cibra, norb, nelec, link_index, 0) dm2ba = dm2ba.transpose(3,2,1,0) if reorder: dm1a, dm2aa = rdm.reorder_rdm(dm1a, dm2aa, inplace=True) dm1b, dm2bb = rdm.reorder_rdm(dm1b, dm2bb, inplace=True) return (dm1a, dm1b), (dm2aa, dm2ab, dm2ba, dm2bb)
def trans_rdm12s(cibra, ciket, norb, nelec, link_index=None, reorder=True): '''Spin separated transition 1- and 2-particle density matrices. ''' dm1a, dm2aa = rdm.make_rdm12_spin1('FCItdm12kern_a', cibra, ciket, norb, nelec, link_index, 2) dm1b, dm2bb = rdm.make_rdm12_spin1('FCItdm12kern_b', cibra, ciket, norb, nelec, link_index, 2) _, dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', cibra, ciket, norb, nelec, link_index, 0) _, dm2ba = rdm.make_rdm12_spin1('FCItdm12kern_ab', ciket, cibra, norb, nelec, link_index, 0) dm2ba = dm2ba.transpose(3,2,1,0) if reorder: dm1a, dm2aa = rdm.reorder_rdm(dm1a, dm2aa, inplace=True) dm1b, dm2bb = rdm.reorder_rdm(dm1b, dm2bb, inplace=True) return (dm1a, dm1b), (dm2aa, dm2ab, dm2ba, dm2bb)
def trans_rdm12s(cibra, ciket, norb, nelec, link_index=None, reorder=True): '''Spin separated transition 1- and 2-particle density matrices. ''' dm1a, dm2aa = rdm.make_rdm12_spin1('FCItdm12kern_a', cibra, ciket, norb, nelec, link_index, 2) dm1b, dm2bb = rdm.make_rdm12_spin1('FCItdm12kern_b', cibra, ciket, norb, nelec, link_index, 2) _, dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', cibra, ciket, norb, nelec, link_index, 0) _, dm2ba = rdm.make_rdm12_spin1('FCItdm12kern_ab', ciket, cibra, norb, nelec, link_index, 0) dm2ba = dm2ba.transpose(3, 2, 1, 0) if reorder: dm1a, dm2aa = rdm.reorder_rdm(dm1a, dm2aa, inplace=True) dm1b, dm2bb = rdm.reorder_rdm(dm1b, dm2bb, inplace=True) return (dm1a, dm1b), (dm2aa, dm2ab, dm2ba, dm2bb)
def trans_rdm12(cibra, ciket, norb, nelec, link_index=None, reorder=True): #(dm1a, dm1b), (dm2aa, dm2ab, dm2ba, dm2bb) = \ # trans_rdm12s(cibra, ciket, norb, nelec, link_index, reorder) #return dm1a+dm1b, dm2aa+dm2ab+dm2ba+dm2bb dm1, dm2 = rdm.make_rdm12_spin1('FCItdm12kern_sf', cibra, ciket, norb, nelec, link_index, 2) if reorder: dm1, dm2 = rdm.reorder_rdm(dm1, dm2, inplace=True) return dm1, dm2
def make_rdm12(fcivec, norb, nelec, link_index=None, reorder=True): #(dm1a, dm1b), (dm2aa, dm2ab, dm2bb) = \ # make_rdm12s(fcivec, norb, nelec, link_index, reorder) #return dm1a+dm1b, dm2aa+dm2ab+dm2ab.transpose(2,3,0,1)+dm2bb dm1, dm2 = rdm.make_rdm12_spin1('FCIrdm12kern_sf', fcivec, fcivec, norb, nelec, link_index, 1) if reorder: dm1, dm2 = rdm.reorder_rdm(dm1, dm2, inplace=True) return dm1, dm2
def make_rdm12s(fcivec, norb, nelec, link_index=None, reorder=True): r'''Spin searated 1- and 2-particle density matrices, (alpha,beta) for 1-particle density matrices. (alpha,alpha,alpha,alpha), (alpha,alpha,beta,beta), (beta,beta,beta,beta) for 2-particle density matrices. NOTE the 2pdm is :math:`\langle p^\dagger q^\dagger s r\rangle` but is stored as [p,r,q,s] ''' dm1a, dm2aa = rdm.make_rdm12_spin1('FCIrdm12kern_a', fcivec, fcivec, norb, nelec, link_index, 1) dm1b, dm2bb = rdm.make_rdm12_spin1('FCIrdm12kern_b', fcivec, fcivec, norb, nelec, link_index, 1) _, dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', fcivec, fcivec, norb, nelec, link_index, 0) if reorder: dm1a, dm2aa = rdm.reorder_rdm(dm1a, dm2aa, inplace=True) dm1b, dm2bb = rdm.reorder_rdm(dm1b, dm2bb, inplace=True) return (dm1a, dm1b), (dm2aa, dm2ab, dm2bb)
def trans_rdm12(cibra, ciket, norb, nelec, link_index=None, reorder=True): '''Spin traced transition 1- and 2-particle density matrices. ''' #(dm1a, dm1b), (dm2aa, dm2ab, dm2ba, dm2bb) = \ # trans_rdm12s(cibra, ciket, norb, nelec, link_index, reorder) #return dm1a+dm1b, dm2aa+dm2ab+dm2ba+dm2bb dm1, dm2 = rdm.make_rdm12_spin1('FCItdm12kern_sf', cibra, ciket, norb, nelec, link_index, 2) if reorder: dm1, dm2 = rdm.reorder_rdm(dm1, dm2, inplace=True) return dm1, dm2
def make_rdm12(fcivec, norb, nelec, link_index=None, reorder=True): r'''Spin traced 1- and 2-particle density matrices, NOTE the 2pdm is :math:`\langle p^\dagger q^\dagger s r\rangle` but is stored as [p,r,q,s] ''' #(dm1a, dm1b), (dm2aa, dm2ab, dm2bb) = \ # make_rdm12s(fcivec, norb, nelec, link_index, reorder) #return dm1a+dm1b, dm2aa+dm2ab+dm2ab.transpose(2,3,0,1)+dm2bb dm1, dm2 = rdm.make_rdm12_spin1('FCIrdm12kern_sf', fcivec, fcivec, norb, nelec, link_index, 1) if reorder: dm1, dm2 = rdm.reorder_rdm(dm1, dm2, inplace=True) return dm1, dm2
def trans_rdm12(cibra, ciket, norb, nelec, link_index=None, reorder=True): r'''Spin traced transition 1- and 2-particle transition density matrices. 1pdm[p,q] = :math:`\langle q^\dagger p\rangle`; 2pdm[p,q,r,s] = :math:`\langle p^\dagger r^\dagger s q\rangle`. ''' #(dm1a, dm1b), (dm2aa, dm2ab, dm2ba, dm2bb) = \ # trans_rdm12s(cibra, ciket, norb, nelec, link_index, reorder) #return dm1a+dm1b, dm2aa+dm2ab+dm2ba+dm2bb dm1, dm2 = rdm.make_rdm12_spin1('FCItdm12kern_sf', cibra, ciket, norb, nelec, link_index, 2) if reorder: dm1, dm2 = rdm.reorder_rdm(dm1, dm2, inplace=True) return dm1, dm2
def make_rdm2s(civec_strs, norb, nelec, link_index=None, **kwargs): ci_coeff, nelec, ci_strs = _unpack(civec_strs, nelec) if link_index is None: cd_indexa = cre_des_linkstr(ci_strs[0], norb, nelec[0]) dd_indexa = des_des_linkstr(ci_strs[0], norb, nelec[0]) cd_indexb = cre_des_linkstr(ci_strs[1], norb, nelec[1]) dd_indexb = des_des_linkstr(ci_strs[1], norb, nelec[1]) else: cd_indexa, dd_indexa, cd_indexb, dd_indexb = link_index na, nlinka = cd_indexa.shape[:2] nb, nlinkb = cd_indexb.shape[:2] ma, mlinka = dd_indexa.shape[:2] mb, mlinkb = dd_indexb.shape[:2] fcivec = ci_coeff.reshape(na, nb) # (bb|aa) and (aa|bb) dm2ab = rdm.make_rdm12_spin1("FCItdm12kern_ab", fcivec, fcivec, norb, nelec, (cd_indexa, cd_indexb), 0)[1] # (aa|aa) if nelec[0] > 1: dm2aa = numpy.empty([norb] * 4) libfci.SCIrdm2_aaaa( libfci.SCIrdm2kern_aaaa, dm2aa.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(ma), ctypes.c_int(mlinka), dd_indexa.ctypes.data_as(ctypes.c_void_p), ) # (bb|bb) if nelec[1] > 1: dm2bb = numpy.empty([norb] * 4) fcivecT = lib.transpose(fcivec) libfci.SCIrdm2_aaaa( libfci.SCIrdm2kern_aaaa, dm2bb.ctypes.data_as(ctypes.c_void_p), fcivecT.ctypes.data_as(ctypes.c_void_p), fcivecT.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(nb), ctypes.c_int(na), ctypes.c_int(mb), ctypes.c_int(mlinkb), dd_indexb.ctypes.data_as(ctypes.c_void_p), ) return dm2aa, dm2ab, dm2bb
def make_rdm2s(civec_strs, norb, nelec, link_index=None, **kwargs): r'''Spin separated 2-particle density matrices. The return values include three density matrices: (alpha,alpha,alpha,alpha), (alpha,alpha,beta,beta), (beta,beta,beta,beta) 2pdm[p,q,r,s] = :math:`\langle p^\dagger r^\dagger s q\rangle` ''' ci_coeff, nelec, ci_strs = _unpack(civec_strs, nelec) if link_index is None: cd_indexa = cre_des_linkstr(ci_strs[0], norb, nelec[0]) dd_indexa = des_des_linkstr(ci_strs[0], norb, nelec[0]) cd_indexb = cre_des_linkstr(ci_strs[1], norb, nelec[1]) dd_indexb = des_des_linkstr(ci_strs[1], norb, nelec[1]) else: cd_indexa, dd_indexa, cd_indexb, dd_indexb = link_index na, nlinka = cd_indexa.shape[:2] nb, nlinkb = cd_indexb.shape[:2] fcivec = ci_coeff.reshape(na,nb) # (bb|aa) and (aa|bb) dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', fcivec, fcivec, norb, nelec, (cd_indexa,cd_indexb), 0)[1] # (aa|aa) dm2aa = numpy.zeros([norb]*4) if nelec[0] > 1: ma, mlinka = dd_indexa.shape[:2] libfci.SCIrdm2_aaaa(libfci.SCIrdm2kern_aaaa, dm2aa.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(ma), ctypes.c_int(mlinka), dd_indexa.ctypes.data_as(ctypes.c_void_p)) # (bb|bb) dm2bb = numpy.zeros([norb]*4) if nelec[1] > 1: mb, mlinkb = dd_indexb.shape[:2] fcivecT = lib.transpose(fcivec) libfci.SCIrdm2_aaaa(libfci.SCIrdm2kern_aaaa, dm2bb.ctypes.data_as(ctypes.c_void_p), fcivecT.ctypes.data_as(ctypes.c_void_p), fcivecT.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(nb), ctypes.c_int(na), ctypes.c_int(mb), ctypes.c_int(mlinkb), dd_indexb.ctypes.data_as(ctypes.c_void_p)) return dm2aa, dm2ab, dm2bb
def make_rdm2s(civec_strs, norb, nelec, link_index=None, **kwargs): r'''Spin separated 2-particle density matrices. The return values include three density matrices: (alpha,alpha,alpha,alpha), (alpha,alpha,beta,beta), (beta,beta,beta,beta) 2pdm[p,q,r,s] = :math:`\langle p^\dagger r^\dagger s q\rangle` ''' ci_coeff, nelec, ci_strs = _unpack(civec_strs, nelec) if link_index is None: cd_indexa = cre_des_linkstr(ci_strs[0], norb, nelec[0]) dd_indexa = des_des_linkstr(ci_strs[0], norb, nelec[0]) cd_indexb = cre_des_linkstr(ci_strs[1], norb, nelec[1]) dd_indexb = des_des_linkstr(ci_strs[1], norb, nelec[1]) else: cd_indexa, dd_indexa, cd_indexb, dd_indexb = link_index na, nlinka = cd_indexa.shape[:2] nb, nlinkb = cd_indexb.shape[:2] ma, mlinka = dd_indexa.shape[:2] mb, mlinkb = dd_indexb.shape[:2] fcivec = ci_coeff.reshape(na, nb) # (bb|aa) and (aa|bb) dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', fcivec, fcivec, norb, nelec, (cd_indexa, cd_indexb), 0)[1] # (aa|aa) if nelec[0] > 1: dm2aa = numpy.empty([norb] * 4) libfci.SCIrdm2_aaaa(libfci.SCIrdm2kern_aaaa, dm2aa.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(ma), ctypes.c_int(mlinka), dd_indexa.ctypes.data_as(ctypes.c_void_p)) # (bb|bb) if nelec[1] > 1: dm2bb = numpy.empty([norb] * 4) fcivecT = lib.transpose(fcivec) libfci.SCIrdm2_aaaa(libfci.SCIrdm2kern_aaaa, dm2bb.ctypes.data_as(ctypes.c_void_p), fcivecT.ctypes.data_as(ctypes.c_void_p), fcivecT.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(nb), ctypes.c_int(na), ctypes.c_int(mb), ctypes.c_int(mlinkb), dd_indexb.ctypes.data_as(ctypes.c_void_p)) return dm2aa, dm2ab, dm2bb
def make_rdm2s(civec_strs, norb, nelec, link_index=None, **kwargs): ci_coeff, nelec, ci_strs = _unpack(civec_strs, nelec) if link_index is None: cd_indexa = cre_des_linkstr(ci_strs[0], norb, nelec[0]) dd_indexa = des_des_linkstr(ci_strs[0], norb, nelec[0]) cd_indexb = cre_des_linkstr(ci_strs[1], norb, nelec[1]) dd_indexb = des_des_linkstr(ci_strs[1], norb, nelec[1]) else: cd_indexa, dd_indexa, cd_indexb, dd_indexb = link_index na, nlinka = cd_indexa.shape[:2] nb, nlinkb = cd_indexb.shape[:2] ma, mlinka = dd_indexa.shape[:2] mb, mlinkb = dd_indexb.shape[:2] fcivec = ci_coeff.reshape(na, nb) # (bb|aa) and (aa|bb) dm2ab = rdm.make_rdm12_spin1('FCItdm12kern_ab', fcivec, fcivec, norb, nelec, (cd_indexa, cd_indexb), 0)[1] # (aa|aa) if nelec[0] > 1: dm2aa = numpy.empty([norb] * 4) libfci.SCIrdm2_aaaa(libfci.SCIrdm2kern_aaaa, dm2aa.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(ma), ctypes.c_int(mlinka), dd_indexa.ctypes.data_as(ctypes.c_void_p)) # (bb|bb) if nelec[1] > 1: dm2bb = numpy.empty([norb] * 4) fcivecT = lib.transpose(fcivec) libfci.SCIrdm2_aaaa(libfci.SCIrdm2kern_aaaa, dm2bb.ctypes.data_as(ctypes.c_void_p), fcivecT.ctypes.data_as(ctypes.c_void_p), fcivecT.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(nb), ctypes.c_int(na), ctypes.c_int(mb), ctypes.c_int(mlinkb), dd_indexb.ctypes.data_as(ctypes.c_void_p)) return dm2aa, dm2ab, dm2bb
def make_rdm12(fcivec, norb, nelec, link_index=None, reorder=True): r'''Spin traced 1- and 2-particle density matrices. 1pdm[p,q] = :math:`\langle q_\alpha^\dagger p_\alpha \rangle + \langle q_\beta^\dagger p_\beta \rangle`; 2pdm[p,q,r,s] = :math:`\langle p_\alpha^\dagger r_\alpha^\dagger s_\alpha q_\alpha\rangle + \langle p_\beta^\dagger r_\alpha^\dagger s_\alpha q_\beta\rangle + \langle p_\alpha^\dagger r_\beta^\dagger s_\beta q_\alpha\rangle + \langle p_\beta^\dagger r_\beta^\dagger s_\beta q_\beta\rangle`. Energy should be computed as E = einsum('pq,qp', h1, 1pdm) + 1/2 * einsum('pqrs,pqrs', eri, 2pdm) where h1[p,q] = <p|h|q> and eri[p,q,r,s] = (pq|rs) ''' #(dm1a, dm1b), (dm2aa, dm2ab, dm2bb) = \ # make_rdm12s(fcivec, norb, nelec, link_index, reorder) #return dm1a+dm1b, dm2aa+dm2ab+dm2ab.transpose(2,3,0,1)+dm2bb dm1, dm2 = rdm.make_rdm12_spin1('FCIrdm12kern_sf', fcivec, fcivec, norb, nelec, link_index, 1) if reorder: dm1, dm2 = rdm.reorder_rdm(dm1, dm2, inplace=True) return dm1, dm2