You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以Python数组风格在Fortran中处理派生类型与嵌套结构?

Fortran实现Python嵌套列表式结构的方案

要在Fortran中实现类似Python嵌套列表的可迭代、可索引访问结构,核心是用派生类型+动态数组替代带命名成员的静态派生类型,这样就能实现数组式访问、迭代和元素数量获取。以下是具体实现:

1. 定义嵌套派生类型结构

先从最底层的基函数类型开始,逐层向上构建分子的嵌套结构:

module gaussian_types
    implicit none

    ! 最底层:基函数类型,对应Python的primitive_gaussian类
    type :: PrimitiveGaussian
        real :: alpha      ! 指数参数
        real :: coeff      ! 收缩系数
        integer :: l, m, n ! 角量子数
    end type PrimitiveGaussian

    ! 中间层:单个原子的基组,对应Python中单个原子的基函数列表
    type :: AtomBasis
        character(len=2) :: atom_symbol       ! 原子符号(如"H"、"O")
        type(PrimitiveGaussian), allocatable :: pgs(:)  ! 该原子的所有基函数
    end type AtomBasis

    ! 顶层:分子结构,对应Python的molecule嵌套列表
    type :: Molecule
        type(AtomBasis), allocatable :: atoms(:)  ! 分子中的所有原子基组
    end type Molecule

contains
    ! 初始化原子基组的工具子程序
    subroutine init_atom_basis(atom, symbol, pg_list)
        type(AtomBasis), intent(out) :: atom
        character(len=*), intent(in) :: symbol
        type(PrimitiveGaussian), intent(in) :: pg_list(:)
        atom%atom_symbol = symbol
        allocate(atom%pgs(size(pg_list)))
        atom%pgs = pg_list
    end subroutine init_atom_basis

    ! 初始化分子的工具子程序
    subroutine init_molecule(mol, atom_list)
        type(Molecule), intent(out) :: mol
        type(AtomBasis), intent(in) :: atom_list(:)
        allocate(mol%atoms(size(atom_list)))
        mol%atoms = atom_list
    end subroutine init_molecule

    ! 动态追加基函数到原子基组(类似Python列表的append)
    subroutine append_pg_to_atom(atom, new_pg)
        type(AtomBasis), intent(inout) :: atom
        type(PrimitiveGaussian), intent(in) :: new_pg
        type(PrimitiveGaussian), allocatable :: temp(:)

        if (allocated(atom%pgs)) then
            allocate(temp(size(atom%pgs)+1))
            temp(1:size(atom%pgs)) = atom%pgs
            temp(size(atom%pgs)+1) = new_pg
            deallocate(atom%pgs)
            call move_alloc(temp, atom%pgs)
        else
            allocate(atom%pgs(1))
            atom%pgs(1) = new_pg
        end if
    end subroutine append_pg_to_atom

end module gaussian_types

2. 使用示例:访问、迭代与数量获取

以下代码演示如何初始化结构、像数组一样访问属性、嵌套迭代,以及获取各层元素数量:

program test_molecule
    use gaussian_types
    implicit none

    type(PrimitiveGaussian) :: h_pg1, h_pg2, o_pg1
    type(AtomBasis) :: h1_basis, h2_basis, o_basis
    type(Molecule) :: water_mol
    integer :: i, k

    ! 初始化基函数实例
    h_pg1 = PrimitiveGaussian(alpha=0.5, coeff=1.0, l=0, m=0, n=0)
    h_pg2 = PrimitiveGaussian(alpha=0.1, coeff=0.5, l=0, m=0, n=0)
    o_pg1 = PrimitiveGaussian(alpha=1.0, coeff=0.8, l=0, m=0, n=0)

    ! 初始化原子基组
    call init_atom_basis(h1_basis, "H", [h_pg1, h_pg2])
    call init_atom_basis(h2_basis, "H", [h_pg1])
    call init_atom_basis(o_basis, "O", [o_pg1])
    ! 动态给氧原子追加一个基函数
    call append_pg_to_atom(o_basis, PrimitiveGaussian(alpha=0.3, coeff=0.2, l=1, m=0, n=0))

    ! 初始化水分子
    call init_molecule(water_mol, [o_basis, h1_basis, h2_basis])

    ! 1. 便捷访问属性(对应Python的 molecule[i][k].some_value)
    ! 注意:Fortran数组下标从1开始,Python从0开始,需调整索引
    print *, "氧原子第2个基函数的指数:", water_mol%atoms(1)%pgs(2)%alpha

    ! 2. 嵌套迭代所有基函数
    print *, new_line('a')//"=== 遍历所有基函数 ==="
    do i = 1, size(water_mol%atoms)
        print *, "原子", i, "(", trim(water_mol%atoms(i)%atom_symbol), "):"
        do k = 1, size(water_mol%atoms(i)%pgs)
            print *, "  基函数", k, ": alpha=", water_mol%atoms(i)%pgs(k)%alpha, &
                     ",coeff=", water_mol%atoms(i)%pgs(k)%coeff
        end do
    end do

    ! 3. 获取各层元素数量
    print *, new_line('a')//"=== 各层元素数量 ==="
    print *, "分子中的原子数:", size(water_mol%atoms)
    do i = 1, size(water_mol%atoms)
        print *, "原子", i, "的基函数数量:", size(water_mol%atoms(i)%pgs)
    end do

    ! 显式释放内存(程序结束时会自动释放,大型项目建议显式管理)
    deallocate(water_mol%atoms)
    deallocate(h1_basis%pgs, h2_basis%pgs, o_basis%pgs)

end program test_molecule

3. 核心优势说明

  • 数组式访问:通过mol%atoms(i)%pgs(k)%attr实现类似Python的索引访问,完全满足便捷性需求。
  • 可迭代性:结合size()函数和do循环,直接实现嵌套迭代,解决了静态命名成员无法遍历的问题。
  • 动态扩展:通过append_pg_to_atom这类子程序,可以动态添加元素,模拟Python列表的灵活性。
  • 元素数量获取:size()函数对动态数组完全有效,直接获取各层的元素数量,替代无效的Extent()。

内容的提问来源于stack exchange,提问作者electron_correlation

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 07:24:22