GrapeClass.f90 Source File


Contents

Source Code


Source Code

module GrapeClass
    use LeafClass
    use StemClass
    use RootClass
    implicit none

    type :: Grape_

        ! 節-節点データ構造
        type(Mesh_) :: struct 
        integer(int32),allocatable :: leaf2stem(:,:)
        integer(int32),allocatable :: stem2stem(:,:)
        integer(int32),allocatable :: root2stem(:,:)
        integer(int32),allocatable :: root2root(:,:)

        real(real64)   :: mainstem_length
        real(real64)   :: mainstem_width
        integer(int32) :: mainstem_node

        real(real64)   :: mainroot_length
        real(real64)   :: mainroot_width
        integer(int32) :: mainroot_node

        integer(int32) :: num_branch
        integer(int32) :: num_branch_node

        integer(int32) :: num_branch_root
        integer(int32) :: num_branch_root_node

        real(real64) :: ms_angle_ave = 0.0d0
        real(real64) :: ms_angle_sig = 0.0d0
        real(real64),allocatable :: br_angle_ave_x(:) 
        real(real64),allocatable :: br_angle_sig_x(:) 
        real(real64),allocatable :: br_angle_ave_z(:) 
        real(real64),allocatable :: br_angle_sig_z(:) 



        real(real64),allocatable :: peti_size_ave(:)
        real(real64),allocatable :: peti_size_sig(:)
        real(real64),allocatable :: peti_width_ave(:)
        real(real64),allocatable :: peti_width_sig(:)
        real(real64),allocatable :: peti_angle_ave(:)
        real(real64),allocatable :: peti_angle_sig(:)

        real(real64),allocatable :: leaf_thickness_ave(:)
        real(real64),allocatable :: leaf_thickness_sig(:)
        real(real64),allocatable :: leaf_angle_ave(:)
        real(real64),allocatable :: leaf_angle_sig(:)
        real(real64),allocatable :: leaf_length_ave(:)
        real(real64),allocatable :: leaf_length_sig(:)
        real(real64),allocatable :: leaf_width_ave(:)
        real(real64),allocatable :: leaf_width_sig(:)


        integer(int32),allocatable :: br_node(:)
        integer(int32),allocatable :: br_from(:)
        real(real64),allocatable :: br_length(:)
        real(real64),allocatable :: br_width(:)

        
        integer(int32) :: num_leaf
        integer(int32) :: num_stem
        integer(int32) :: num_root


        ! 器官オブジェクト配列
        type(FEMDomain_),allocatable :: leaf_list(:)
        type(FEMDomain_),allocatable :: stem_list(:)
        type(FEMDomain_),allocatable :: root_list(:)

        character(:),allocatable :: LeafSurfaceData
        type(Leaf_),allocatable :: Leaf(:)
        type(Stem_),allocatable :: Stem(:)
        type(Root_),allocatable :: Root(:)


        
    contains
        procedure :: create => createGrape
        procedure,public :: msh => mshGrape
        procedure,public :: vtk => vtkGrape
        procedure,public :: stl => stlGrape
        procedure,public :: json => jsonGrape
        procedure,public :: move => moveGrape
    end type
contains

! #############################################################
subroutine createGrape(obj,config)
    class(Grape_),intent(inout) :: obj
    character(*),intent(in) :: config
    character(:),allocatable :: line
    type(IO_) :: grapeconfig
    type(Random_) :: random
    integer(int32)::i,n,j,k,num_leaf,num_stem_node,num_branch_branch

    obj%LeafSurfaceData = trim(grapeconfig%parse(config,key1="LeafSurfaceData"))
    obj%mainstem_length = freal(grapeconfig%parse(config,key1="Mainstem",key2="Length"))
    obj%mainstem_width = freal(grapeconfig%parse(config,key1="Mainstem",key2="Width"))
    obj%mainstem_node = fint(grapeconfig%parse(config,key1="Mainstem",key2="Node"))
    obj%ms_angle_ave = freal(grapeconfig%parse(config,key1="Mainstem",key2="ms_angle_ave"))
    obj%ms_angle_sig = freal(grapeconfig%parse(config,key1="Mainstem",key2="ms_angle_sig"))

    
    ! get number of branch && number of node
    obj%num_branch=1
    obj%num_branch_node=0
    do 
        line = grapeconfig%parse(config,key1="Branch#"//trim(str(obj%num_branch)),key2="Node" )
        if(len(trim(line))==0)then
            obj%num_branch = obj%num_branch -1
            exit
        else
            obj%num_branch = obj%num_branch  + 1
            obj%num_branch_node = obj%num_branch_node + fint(line)
            ! Further branch
            ! line = grapeconfig%parse(config,key1="Branch#"//trim(str(i)),key2="Branch#1")    
            ! num_branch_branch = fint(line)
            ! if(num_branch_branch/=0)then
            !     ! 2nd order branch
            !     line = grapeconfig%parse(config,key1="Branch#"//trim(str(i)),key2="Branch#1")    
            ! endif
            cycle
        endif
    enddo


    allocate(obj%br_node(obj%num_branch) )
    allocate(obj%br_from(obj%num_branch) )
    allocate(obj%br_length(obj%num_branch) )
    allocate(obj%br_width(obj%num_branch) )
    allocate(obj%br_angle_ave_x(obj%num_branch) )
    allocate(obj%br_angle_sig_x(obj%num_branch) )
    allocate(obj%br_angle_ave_z(obj%num_branch) )
    allocate(obj%br_angle_sig_z(obj%num_branch) )

    allocate(obj%peti_size_ave(obj%num_branch))
    allocate(obj%peti_size_sig(obj%num_branch))
    allocate(obj%peti_width_ave(obj%num_branch))
    allocate(obj%peti_width_sig(obj%num_branch))
    allocate(obj%peti_angle_ave(obj%num_branch))
    allocate(obj%peti_angle_sig(obj%num_branch))

    allocate(obj%leaf_thickness_ave(obj%num_branch))
    allocate(obj%leaf_thickness_sig(obj%num_branch))
    allocate(obj%leaf_angle_ave(obj%num_branch))
    allocate(obj%leaf_angle_sig(obj%num_branch))
    allocate(obj%leaf_length_ave(obj%num_branch))
    allocate(obj%leaf_length_sig(obj%num_branch))
    allocate(obj%leaf_width_ave(obj%num_branch))
    allocate(obj%leaf_width_sig(obj%num_branch))


    do i=1,obj%num_branch
        line = grapeconfig%parse(config,key1="Branch#"//trim(str(i)),key2="Node" )    
        obj%br_node(i) = fint(line)
        line = grapeconfig%parse(config,key1="Branch#"//trim(str(i)),key2="From" )    
        obj%br_from(i) = fint(line)
        line = grapeconfig%parse(config,key1="Branch#"//trim(str(i)),key2="Length" )    
        obj%br_length(i) = freal(line)
        line = grapeconfig%parse(config,key1="Branch#"//trim(str(i)),key2="Width" )    
        obj%br_width(i) = freal(line)
        obj%br_angle_ave_x(i) = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="br_angle_ave_x"))
        obj%br_angle_ave_z(i) = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="br_angle_ave_z"))
        obj%br_angle_sig_x(i) = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="br_angle_sig_x"))
        obj%br_angle_sig_z(i) = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="br_angle_sig_z"))
        obj%peti_size_ave(i)  = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="peti_size_ave"))
        obj%peti_size_sig(i)  = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="peti_size_sig"))
        obj%peti_width_ave(i) = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="peti_width_ave"))
        obj%peti_width_sig(i) = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="peti_width_sig"))
        obj%peti_angle_ave(i) = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="peti_angle_ave"))
        obj%peti_angle_sig(i) = freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="peti_angle_sig"))

        obj%leaf_thickness_ave(i)= freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="leaf_thickness_ave"))
        obj%leaf_thickness_sig(i)= freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="leaf_thickness_sig"))
        obj%leaf_angle_ave(i)= freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="leaf_angle_ave"))
        obj%leaf_angle_sig(i)= freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="leaf_angle_sig"))
        obj%leaf_length_ave(i)= freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="leaf_length_ave"))
        obj%leaf_length_sig(i)= freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="leaf_length_sig"))
        obj%leaf_width_ave(i)= freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="leaf_width_ave"))
        obj%leaf_width_sig(i)= freal(grapeconfig%parse(&
            config,key1="Branch#"//trim(str(i)),key2="leaf_width_sig"))
        
    enddo

    obj%mainroot_length = freal(grapeconfig%parse(config,key1="Mainroot",key2="Length"))
    obj%mainroot_width = freal(grapeconfig%parse(config,key1="Mainroot",key2="Width"))
    obj%mainroot_node = fint(grapeconfig%parse(config,key1="Mainroot",key2="Node"))



    ! get number of branch && number of node
    obj%num_branch_root=1
    obj%num_branch_root_node=0
    do 
        line = grapeconfig%parse(config,key1="Branchroot#"//trim(str(obj%num_branch_root)),key2="Node" )
        if(len(trim(line))==0)then
            obj%num_branch_root = obj%num_branch_root -1
            exit
        else
            obj%num_branch_root = obj%num_branch_root  + 1
            obj%num_branch_root_node = obj%num_branch_root_node + fint(line)
            cycle
        endif
    enddo

    obj%num_leaf =obj%num_branch_node + obj%mainstem_node 
    obj%num_stem =obj%num_branch_node + obj%mainstem_node 
    obj%num_root =obj%num_branch_root_node + obj%mainroot_node

    allocate(obj%leaf_list(obj%num_leaf))
    allocate(obj%stem_list(obj%num_stem))
    allocate(obj%root_list(obj%num_root))

    allocate(obj%leaf(obj%num_leaf*2))
    allocate(obj%stem(obj%num_stem*2))
    allocate(obj%root(obj%num_root*2))



    obj%leaf2stem = zeros( obj%num_leaf , obj%num_stem*2 ) 
    obj%stem2stem = zeros( obj%num_stem*2 , obj%num_stem*2 ) 
    obj%root2stem = zeros( obj%num_root , obj%num_stem*2 ) 
    obj%root2root = zeros( obj%num_root , obj%num_root ) 


    ! set mainstem
    do i=1,obj%mainstem_node

        call obj%stem(i)%init()
        call obj%stem(i)%resize(&
            x = obj%mainstem_width, &
            y = obj%mainstem_width, &
            z = obj%mainstem_length/dble(obj%mainstem_node) &
            )
        call obj%stem(i)%rotate(&
            x = radian(random%gauss(mu=obj%ms_angle_ave,sigma=obj%ms_angle_sig)),  &
            y = radian(random%gauss(mu=obj%ms_angle_ave,sigma=obj%ms_angle_sig)),  &
            z = radian(random%gauss(mu=obj%ms_angle_ave,sigma=obj%ms_angle_sig))   &
            )
    enddo

    do i=1,obj%mainstem_node-1
        call obj%stem(i+1)%connect("=>",obj%stem(i))
        obj%stem2stem(i+1,i) = 1
    enddo

    ! set branches
    k=obj%mainstem_node
    do i=1,size(obj%br_node)
        do j=1, obj%br_node(i)
            k = k + 1
            call obj%stem(k)%init()
            call obj%stem(k)%resize(&
                x = obj%br_width(i), &
                y = obj%br_width(i), &
                z = obj%br_length(i)/dble(obj%br_node(i) ) &
                )
                
            call obj%stem(k)%rotate(&
                x = radian(random%gauss(mu=obj%br_angle_ave_x(i),sigma=obj%br_angle_sig_x(i) )),  &
                y = 0.0d0,  &
                z = radian(random%gauss(mu=obj%br_angle_ave_z(i),sigma=obj%br_angle_sig_z(i) ))  &
                )                
            
            if(j==1)then
                call obj%stem(k)%connect("=>",obj%stem(obj%br_from(i)  ))
                obj%stem2stem(k,obj%br_from(i) ) = 1
            else
                call obj%stem(k)%connect("=>",obj%stem(k-1))
                obj%stem2stem(k,k-1) = 1
            endif   
        enddo
    enddo
!    


        ! peti and leaf
    num_stem_node = k
    num_leaf = 0
    do i=1, size(obj%br_node)
        do j=1,obj%br_node(i)
            ! 3複葉
            ! add peti
            num_stem_node = num_stem_node +1
            call obj%stem(num_stem_node)%init()

            call obj%stem(num_stem_node)%resize(&
                x = random%gauss(mu=obj%peti_width_ave(i),sigma=obj%peti_width_sig(i)), &
                y = random%gauss(mu=obj%peti_width_ave(i),sigma=obj%peti_width_sig(i)), &
                z = random%gauss(mu=obj%peti_size_ave(i),sigma=obj%peti_size_sig(i)) &
                )
            
            call obj%stem(num_stem_node)%rotate(&
                x = radian(random%gauss(mu=obj%peti_angle_ave(i),sigma=obj%peti_angle_sig(i) )),  &
                y = 0.0d0,  &
                z = radian(360.0d0*random%random() )   &
                )      
            
            !obj%leaf2stem(num_stem_node,i) = 1 
            if(i==1)then
                call obj%stem(num_stem_node)%connect("=>",obj%stem( j + obj%mainroot_node))
                obj%stem2stem(num_stem_node, j + obj%mainroot_node ) = 1            
            else
                call obj%stem(num_stem_node)%connect("=>",obj%stem( j + sum( obj%br_node(1:i-1) ) + obj%mainroot_node ))
                obj%stem2stem(num_stem_node, j + sum( obj%br_node(1:i-1) ) + obj%mainroot_node ) = 1            
            endif
            

            ! add leaves
            
            num_leaf=num_leaf+1
            !call obj%leaf(num_leaf)%create(filename=trim(obj%LeafSurfaceData))
            call obj%leaf(num_leaf)%create(filename=trim(obj%LeafSurfaceData) )
            call obj%leaf(num_leaf)%femdomain%resize(&
                    z = random%gauss(mu=obj%leaf_thickness_ave(i),sigma=obj%leaf_thickness_sig(i))  , &
                    x = random%gauss(mu=obj%leaf_length_ave(i)   ,sigma=obj%leaf_length_sig(i)) , &
                    y = random%gauss(mu=obj%leaf_width_ave(i)    ,sigma=obj%leaf_width_sig(i)) &
                )
            call obj%leaf(num_leaf)%femdomain%rotate(&
                    x = radian(random%gauss(mu=obj%leaf_angle_ave(i),sigma=obj%leaf_angle_sig(i))), &
                    y = 0.0d0, &
                    z = radian(random%random()*360.0d0) &
                )
            call obj%leaf(num_leaf)%connect("=>",obj%stem(num_stem_node))
                obj%leaf2stem(num_leaf,num_stem_node) = 1
        enddo
    enddo



end subroutine
! #############################################################


! ########################################
subroutine mshGrape(obj,name,num_threads)
    class(Grape_),intent(inout) :: obj
    character(*),intent(in) :: name
    integer(int32),optional,intent(in) :: num_threads
    integer(int32) :: i,n

    n = input(default=1,option=num_threads)
    !$OMP parallel num_threads(n) private(i)
    !$OMP do 
    do i=1,size(obj%stem)
        !if(obj%stem(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%stem(i)%msh(name=trim(name)//"_stem"//trim(str(i)))
        !endif
    enddo
    !$OMP end do
    !$OMP end parallel

    !$OMP parallel num_threads(n) private(i)
    !$OMP do 
    do i=1,size(obj%root)
        !if(obj%root(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%root(i)%msh(name=trim(name)//"_root"//trim(str(i)))
        !endif
    enddo
    !$OMP end do
    !$OMP end parallel

    !$OMP parallel num_threads(n) private(i)
    !$OMP do 
    do i=1,size(obj%leaf)
        !if(obj%leaf(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%leaf(i)%msh(name=trim(name)//"_leaf"//trim(str(i)))
        !endif
    enddo
    !$OMP end do
    !$OMP end parallel

end subroutine
! ########################################


! ########################################
subroutine vtkGrape(obj,name,num_threads)
    class(Grape_),intent(inout) :: obj
    character(*),intent(in) :: name
    integer(int32),optional,intent(in) :: num_threads
    integer(int32) :: i, n

    n = input(default=1,option=num_threads)
    if(allocated(obj%stem) )then
        !$OMP parallel num_threads(n) private(i)
        !$OMP do 
        do i=1,size(obj%stem)
            !if(obj%stem(i)%femdomain%mesh%empty() .eqv. .false. )then
                call obj%stem(i)%vtk(name=trim(name)//"_stem"//trim(str(i)))
            !endif
        enddo
        !$OMP end do
        !$OMP end parallel
    endif

    
    if(allocated(obj%root))then
        !$OMP parallel num_threads(n) private(i)
        !$OMP do 
        do i=1,size(obj%root)
            !if(obj%root(i)%femdomain%mesh%empty() .eqv. .false. )then
                call obj%root(i)%vtk(name=trim(name)//"_root"//trim(str(i)))
            !endif
        enddo
        !$OMP end do
        !$OMP end parallel
    endif


    
    if(allocated(obj%leaf))then
        !$OMP parallel num_threads(n) private(i)
        !$OMP do 
        do i=1,size(obj%leaf)
            !if(obj%leaf(i)%femdomain%mesh%empty() .eqv. .false. )then
                call obj%leaf(i)%vtk(name=trim(name)//"_leaf"//trim(str(i)))
            !endif
        enddo
        !$OMP end do
        !$OMP end parallel
    endif

end subroutine
! ########################################


! ########################################
subroutine jsonGrape(obj,name)
    class(Grape_),intent(inout) :: obj
    character(*),intent(in) :: name
    integer(int32) :: i,countnum
    type(IO_) :: f

    call f%open(trim(name)//".json")
    call f%write("{")
    countnum=0
    do i=1,size(obj%stem)
        if(obj%stem(i)%femdomain%mesh%empty() .eqv. .false. )then
            countnum=countnum+1
            call f%write('"'//"stem"//trim(str(i))//'":')
            call obj%stem(i)%femdomain%json(name=trim(name)//"_stem"//trim(str(i)),fh=f%fh,endl=.false.)
        endif
    enddo
    call f%write('"num_stem":'//str(countnum)//',' )

    countnum=0
    do i=1,size(obj%root)
        if(obj%root(i)%femdomain%mesh%empty() .eqv. .false. )then
            countnum=countnum+1
            call f%write('"'//"root"//trim(str(i))//'":')
            call obj%root(i)%femdomain%json(name=trim(name)//"_root"//trim(str(i)),fh=f%fh,endl=.false.)
        endif
    enddo
    call f%write('"num_root":'//str(countnum)//',' )
    
    countnum=0
    do i=1,size(obj%leaf)
        if(obj%leaf(i)%femdomain%mesh%empty() .eqv. .false. )then
            countnum=countnum+1
            call f%write('"'//"leaf"//trim(str(i))//'":')
            call obj%leaf(i)%femdomain%json(name=trim(name)//"_leaf"//trim(str(i)),fh=f%fh,endl=.false.)
        endif
    enddo
    call f%write('"num_leaf":'//str(countnum)//',' )
    call f%write('"return_Grape":0')
    call f%write("}")
    call f%close()
end subroutine
! ########################################

! ########################################
subroutine stlGrape(obj,name,num_threads)
    class(Grape_),intent(inout) :: obj
    character(*),intent(in) :: name
    integer(int32),optional,intent(in) :: num_threads
    integer(int32) :: i,n

    n = input(default=1,option=num_threads)
    !call execute_command_line("echo ' ' > "//trim(name)//".stl")
    !$OMP parallel num_threads(n) private(i)
    !$OMP do 
    do i=1,size(obj%stem)
        if(obj%stem(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%stem(i)%stl(name=trim(name)//"_stem"//trim(str(i)))
            !call execute_command_line("cat "//trim(name)//"_stem"//trim(str(i))//"_000001.stl >> "//trim(name)//".stl")
        endif
    enddo
    !$OMP end do
    !$OMP end parallel

    !$OMP parallel num_threads(n) private(i)
    !$OMP do 
    do i=1,size(obj%root)
        if(obj%root(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%root(i)%stl(name=trim(name)//"_root"//trim(str(i)))
            !call execute_command_line("cat "//trim(name)//"_root"//trim(str(i))//"_000001.stl >> "//trim(name)//".stl")
        endif
    enddo
    !$OMP end do
    !$OMP end parallel

    !$OMP parallel num_threads(n) private(i)
    !$OMP do 
    do i=1,size(obj%leaf)
        if(obj%leaf(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%leaf(i)%stl(name=trim(name)//"_leaf"//trim(str(i)))
            !call execute_command_line("cat "//trim(name)//"_leaf"//trim(str(i))//"_000001.stl >> "//trim(name)//".stl")
        endif
    enddo
    !$OMP end do
    !$OMP end parallel


end subroutine
! ########################################

! ########################################
subroutine moveGrape(obj,x,y,z)
    class(Grape_),intent(inout) :: obj
    real(real64),optional,intent(in) :: x,y,z
    integer(int32) :: i

    do i=1,size(obj%stem)
        if(obj%stem(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%stem(i)%move(x=x,y=y,z=z)
        endif
    enddo

    do i=1,size(obj%root)
        if(obj%root(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%root(i)%move(x=x,y=y,z=z)
        endif
    enddo

    do i=1,size(obj%leaf)
        if(obj%leaf(i)%femdomain%mesh%empty() .eqv. .false. )then
            call obj%leaf(i)%move(x=x,y=y,z=z)
        endif
    enddo

end subroutine
! ########################################



end module GrapeClass