module FarmClass use, intrinsic :: iso_fortran_env use SoilClass use SoybeanClass implicit none type :: Farm_ type(Soybean_), allocatable :: Soybean(:, :) type(Soil_) :: Soil integer(int32) :: num_of_ridge integer(int32) :: num_of_plant_per_ridge real(real64) :: width_of_ridge real(real64) :: width_of_plant_per_ridge real(real64) :: length_of_farm, width_of_farm real(real64) :: soil_depth real(real64) :: seed_depth integer(int32) :: total_num_of_plant real(real64) :: plant_density real(real64) :: plant_density_m real(real64) :: total_weight_of_seed real(real64) :: total_area real(real64) :: g_per_100seed real(real64) :: locale(2) real(real64) :: Water_kg contains procedure :: init => initFarm procedure :: sowing => initFarm procedure :: fertilize => fertilizeFarm procedure :: diagnosis => diagnosisFarm procedure :: grow => growFarm procedure :: export => exportFarm end type contains ! ############################################ subroutine initFarm(obj, crop_name, num_of_ridge, num_of_plant_per_ridge, width_of_ridge, & width_of_plant_per_ridge, length_of_farm, width_of_farm, soil_depth, seed_depth, g_per_100seed, & meter, single, Variety) class(Farm_), intent(inout) :: obj integer(int32), optional, intent(in) :: num_of_ridge, num_of_plant_per_ridge real(real64), optional, intent(in) :: width_of_ridge, width_of_plant_per_ridge, soil_depth real(real64), optional, intent(in) :: length_of_farm, width_of_farm, seed_depth, g_per_100seed character(*), intent(in) :: crop_name character(*), optional, intent(in) :: Variety logical, optional, intent(in) :: meter, single integer(int32) :: i, j, k, l, n, m ! input default value obj%num_of_ridge = 10 ! 10 ridge obj%num_of_plant_per_ridge = 10 ! 10 plant per a ridge obj%width_of_ridge = 10.0d0 ! 10.0 cm obj%width_of_plant_per_ridge = 10.0d0 ! 10.0 cm obj%length_of_farm = 100.0d0 ! 1.0 m obj%width_of_farm = 100.0d0 ! 1.0 m obj%soil_depth = input(default=-100.0d0, option=soil_depth) obj%seed_depth = input(default=-3.0d0, option=seed_depth) obj%g_per_100seed = input(default=30.0d0, option=g_per_100seed) if (present(single)) then if (single .eqv. .true.) then obj%num_of_ridge = 1 ! 1 ridge obj%num_of_plant_per_ridge = 1 ! 1 plant per a ridge obj%width_of_ridge = 1.0d0 ! 1.0 cm obj%width_of_plant_per_ridge = 1.0d0 ! 1.0 cm obj%length_of_farm = 1.0d0 ! 1.0 m obj%width_of_farm = 1.0d0 ! 1.0 m end if end if ! determine area default = 1 m^2 = (100 cm)^2 if (present(length_of_farm) .and. present(width_of_farm)) then obj%length_of_farm = length_of_farm obj%width_of_farm = width_of_farm ! if num_of_ridge and num_of_plant_per_ridge are imported if (present(num_of_ridge) .and. present(num_of_plant_per_ridge)) then obj%num_of_ridge = num_of_ridge obj%num_of_plant_per_ridge = num_of_plant_per_ridge obj%width_of_ridge = dble(int(obj%width_of_farm/dble(obj%num_of_ridge))) obj%width_of_plant_per_ridge = dble(int(obj%length_of_farm/dble(obj%num_of_plant_per_ridge))) elseif (present(width_of_ridge) .and. present(width_of_plant_per_ridge)) then obj%width_of_ridge = width_of_ridge obj%width_of_plant_per_ridge = width_of_plant_per_ridge obj%num_of_ridge = int(dble(obj%width_of_farm/dble(obj%width_of_ridge))) obj%num_of_plant_per_ridge = int(dble(obj%length_of_farm/dble(obj%width_of_plant_per_ridge))) else print *, "initFarm #1 >> please give enough information about sowing condition >> default value is set." end if else print *, "initFarm #2 >> please give enough information about sowing condition >> default value is set." end if ! compute total number of plant obj%total_area = obj%length_of_farm*obj%width_of_farm obj%total_num_of_plant = obj%num_of_plant_per_ridge*obj%num_of_ridge obj%plant_density = dble(obj%total_num_of_plant)/dble(obj%total_area) ! plant per cm^2 obj%plant_density_m = obj%plant_density*100.0d0*100.0d0 ! plant per m^2 obj%total_weight_of_seed = obj%g_per_100seed*dble(obj%total_num_of_plant)/100.0d0 ! compute soil profile call obj%soil%init() if (allocated(obj%soybean)) then deallocate (obj%soybean) end if allocate (obj%soybean(obj%num_of_ridge, obj%num_of_plant_per_ridge)) if (crop_name == "soybean" .or. crop_name == "Soybean") then do i = 1, obj%num_of_ridge do j = 1, obj%num_of_plant_per_ridge call obj%soybean(i, j)%sowing(x=obj%width_of_ridge*dble(i - 1), & y=obj%width_of_plant_per_ridge*dble(j - 1), z=obj%seed_depth, Variety=Variety) end do end do else print *, "Sorry, crop_name :: ", crop_name, "is not implemented yet." end if end subroutine ! ############################################ ! ############################################ subroutine fertilizeFarm(obj, N_kg, P_kg, K_kg, Ca_kg, Mg_kg, S_kg, Fe_kg, & Mn_kg, B_kg, Zn_kg, Mo_kg, Cu_kg, Cl_kg) class(Farm_), intent(inout) :: obj ! ================ real(real64), optional, intent(in) :: N_kg real(real64), optional, intent(in) :: P_kg real(real64), optional, intent(in) :: K_kg real(real64), optional, intent(in) :: Ca_kg real(real64), optional, intent(in) :: Mg_kg real(real64), optional, intent(in) :: S_kg ! ================ real(real64), optional, intent(in) :: Fe_kg real(real64), optional, intent(in) :: Mn_kg real(real64), optional, intent(in) :: B_kg real(real64), optional, intent(in) :: Zn_kg real(real64), optional, intent(in) :: Mo_kg real(real64), optional, intent(in) :: Cu_kg real(real64), optional, intent(in) :: Cl_kg ! ================ call obj%Soil%fertilize(N_kg=N_kg, P_kg=P_kg, K_kg=K_kg, Ca_kg=Ca_kg, Mg_kg=Mg_kg, S_kg=S_kg, Fe_kg=Fe_kg, & Mn_kg=Mn_kg, B_kg=B_kg, Zn_kg=Zn_kg, Mo_kg=Mo_kg, Cu_kg=Cu_kg, Cl_kg=Cl_kg) end subroutine ! ############################################ ! ############################################ subroutine exportFarm(obj, FileName, withSTL, withMesh, TimeStep) class(Farm_), intent(inout)::obj integer(int32) :: obj_id, plant_id, i, j, tstep integer(int32), optional, intent(in) :: TimeStep character(*), intent(in) :: FileName logical, optional, intent(in) :: withSTL, withMesh character(200) :: id ! Visualize soybean-field tstep = input(default=0, option=TimeStep) ! initialize obj_id = 1 + tstep plant_id = 0 ! export soybeans do i = 1, obj%num_of_ridge do j = 1, obj%num_of_plant_per_ridge plant_id = plant_id + 1 id = fstring(plant_id) if (present(withSTL)) then if (withSTL .eqv. .true.) then call obj%soybean(i, j)%export(FileName=FileName//id//".geo", SeedID=obj_id, withSTL=withSTL) end if end if if (present(withMesh)) then if (withMesh .eqv. .true.) then call obj%soybean(i, j)%export(FileName=FileName//id//".geo", SeedID=obj_id, withMesh=withMesh) end if end if call obj%soybean(i, j)%export(FileName=FileName//id//".geo", SeedID=obj_id) end do end do print *, "Total "//id//" plants are exported." ! export soil call obj%soil%export(FileName=FileName//id//"soil", format=".geo", objID=obj_id) end subroutine ! ############################################ ! ######################################## subroutine diagnosisFarm(obj, FileName) class(Farm_), intent(inout) :: obj character(*), optional, intent(in)::FileName call obj%Soil%diagnosis(FileName=FileName) end subroutine ! ######################################## ! ######################################## subroutine growFarm(obj, dt, temp, crop_name) class(Farm_), intent(inout) :: obj character(*), intent(in) :: crop_name real(real64), intent(in) :: dt, temp integer(int32) :: i, j if (crop_name == "Soybean" .or. crop_name == "soybean") then do i = 1, size(obj%Soybean, 1) do j = 1, size(obj%Soybean, 2) call obj%Soybean(i, j)%grow(dt=dt, Temp=temp) end do end do end if end subroutine ! ######################################## end module