Расчет поперечной площади реки с использованием большого объема координатных данных, введенных с помощью текстового файла.

Вопрос или проблема

Итак, я хочу рассчитать сеченую площадь реки с неправильным руслом, а также рассчитать сеченую площадь для каждого 1 метра подъема уровня воды до самой высокой точки сечения. Я столкнулся с проблемой, что программа, которую я создал, не могла перейти к следующему сечению, и, надеюсь, я смогу правильно интерполировать, чтобы рассчитать сеченую площадь для каждого 1 метра подъема уровня воды в русле. Следующая проблема заключается в том, что я хочу узнать, как мой код может обнаружить, когда он интерполирует значение глубины (y) между двумя переменными координатных данных, и может быть повторно введен последовательно в одну координатную матрицу сечения. Надеюсь, проблема, которую я выразил, достаточно ясна, и кто-то может мне помочь. Язык программирования, который я использую, – Fortran 90. Спасибо.

program Read_Cross

implicit none
integer, parameter :: dp = selected_real_kind(15,307)
real(kind=dp), allocatable :: x(:), y(:), z(:), Y_New(:), X_New(:) 
real(kind=dp) :: area1, area0, area, min_Y, max_Y, y_diff, X_int
integer :: i, n_Titik, iostat, n_Penampang, Y_Step, Y_Start
character(len=20) :: Header_Penampang

open(unit = 10, file="penampang_multi.txt", status="old", action = 'read')
n_Penampang = 0

do 
    ! Чтение заголовка каждого сечения
    read(10, '(A)', iostat=iostat) Header_Penampang
    if (iostat /= 0) exit  ! Завершить, если достигнут конец файла

    n_Penampang = n_Penampang + 1 ! Подсчет количества сечений

    ! Чтение количества координатных точек для каждого сечения
    read(10, *, iostat=iostat) n_Titik
    if (iostat /= 0) exit ! Завершить, если достигнут конец

    ! Аллоцировать массив в соответствии с количеством точек
    allocate(x(n_Titik), y(n_Titik), z(n_Titik))

    ! Чтение координатных точек из файла
    do i = 1, n_Titik
        read(10, *) x(i), y(i), z(i)
    end do

    ! Начать вычислять площадь сечения как многоугольник
    area1 = 0.0_dp
    do i = 1, n_Titik - 1
        area1 = area1 + (x(i) * y(i + 1) - y(i) * x(i + 1))
    end do
    ! Соединение последней точки с первой
    area1 = area1 + (x(n_Titik) * y(1) - y(n_Titik) * x(1))
    area = abs(area1) / 2.0_dp

    ! Найти минимальные и максимальные значения Y
    min_Y = minval(y)
    max_Y = maxval(y)

    ! Аллоцировать массив Y_New для интерполяции
    allocate(Y_New(n_Titik))
    allocate(X_New(n_Titik))

    Y_Step= int(max_Y-min_Y)

    ! Выполнять интерполяцию новых значений Y
    Y_Start = min_Y
    do i=2, Y_Step
        Y_New(1) = Y_Start+1
        Y_New(i) = Y_New(i-1) + 1.0_dp  ! Увеличение Y на 1 метр
            if (Y_New(i) > max_Y) then      ! Выйти из цикла, если Y_New превышает максимум Y
            end if
    end do

    ! Интерполяция новых значений X на основе новых Y
    do i = 1, Y_Step
        if ((Y_New(i) > y(i)).and.(Y_New(i) < y(i+1))) then
            X_New(i) = x(i) + (x(i+1) - x(i)) * (Y_New(i) - y(i)) / (y(i+1) - y(i))
        end if
    end do

    ! Печать результата координат и площади сечения
    print *, "Сечение", n_Penampang
    do i = 1, n_Titik
        print *, "Координаты (x, y, z): ", x(i), y(i), z(i)
    end do
    do i=1, Y_Step
    print *, "Результат интерполяции глубины", Y_New(i), "м :", X_New(i), Y_New(i)
    end do
    print *, "Площадь сечения: ", area

    ! Освобождение массива после завершения
    deallocate(x, y, z, Y_New, X_New)

end do

close(10)

end program Read_Cross

Это формат файла координат канала, который необходимо ввести в программу с помощью текстового файла

Сечение1

7 (Количество Точек)

0 10 0

0 1 0

2 1 0

3 1 0

4 1 0

4 10 0

0 10 0

Сечение2

4 (Количество Точек)

0 8 5

2 3 5

4 8 5

0 8 5

Сечение3

7 (Количество Точек)

0 12 6

2 8 6

4 8 6

5 8 6

6 8 6

8 12 6

0 12 6

Сечение4

6 (Количество Точек)

0 12 7

2 10 7

4 8 7

5 6 7

7 9 7

8 10 7

Сечение5

6 (Количество Точек)

0 12 8

2 10 8

4 8 8

5 6 8

7 9 8

8 10 8

Сечение6

6 (Количество Точек)

0 12 9

2 10 9

4 8 9

5 6 9

7 9 9

8 10 9

Сечение7

6 (Количество Точек)

0 12 10

2 10 10

4 8 10

5 6 10

7 9 10

8 10 10

Мое ожидание заключается в том, что программа сможет интерполировать координаты, необходимые для расчета сеченой площади канала при каждом 1 метре подъема уровня воды и сможет обрабатывать большое количество и разнообразие сечений, таких как в случае рек.

Ответ или решение

Конечно! Давайте разберёмся с вашей задачей по расчёту поперечного сечения реки, используя данные координат, считанные из текстового файла, с учётом интерполяции глубины для различных уровней воды.

Задача

Вам необходимо рассчитать площадь поперечного сечения реки с неровным руслом. В частности, нужно рассчитать площадь поперечного сечения для каждого увеличения уровня воды на 1 метр, вплоть до максимальной высоты поперечного сечения. Кроме того, вы хотите организовать код так, чтобы он мог обнаруживать, когда проводится интерполяция значения глубины (y) между двумя переменными координатами, и последовательно вводить эти значения в одну матрицу координат поперечного сечения.

Объяснение Код

Ваш код написан на Fortran 90 и в целом имеет правильную структуру. Однако, есть несколько моментов, которые необходимо улучшить, чтобы он выполнял поставленные задачи более эффективно.

Корректировки

  1. Цикл для интерполяции глубины:

    • В текущем коде не предусмотрено, что вы будете проводить интерполяцию между всеми парами (x, y) для каждого 1 метра от минимального до максимального y.
  2. Исправление логики интерполяции:

    • Вместо проверки на if ((Y_New(i) > y(i)).and.(Y_New(i) < y(i + 1))), лучше использовать цикл, который проверяет все точки на наличие текущего значения Y_New, чтобы оно не выходило за пределы массива Y.
  3. Динамическое выделение памяти:

    • Убедитесь, что память для массивов Y_New и X_New выделяется заранее для количества шагов интерполяции Y_Step.

Вот исправленный фрагмент кода с учётом ваших требований:

program Read_Cross
  implicit none
  integer, parameter :: dp = selected_real_kind(15, 307)
  real(kind=dp), allocatable :: x(:), y(:), z(:), Y_New(:), X_New(:) 
  real(kind=dp) :: area1, area, min_Y, max_Y, Y_Step
  integer :: i, n_Titik, iostat, n_Penampang
  character(len=20) :: Header_Penampang

  open(unit = 10, file="penampang_multi.txt", status="old", action = 'read')
  n_Penampang = 0

  do 
      read(10, '(A)', iostat=iostat) Header_Penampang
      if (iostat /= 0) exit

      n_Penampang = n_Penampang + 1 
      read(10, *, iostat=iostat) n_Titik
      if (iostat /= 0) exit 

      allocate(x(n_Titik), y(n_Titik), z(n_Titik))

      do i = 1, n_Titik
          read(10, *) x(i), y(i), z(i)
      end do

      area1 = 0.0_dp
      do i = 1, n_Titik - 1
          area1 = area1 + (x(i) * y(i + 1) - y(i) * x(i + 1))
      end do
      area1 = area1 + (x(n_Titik) * y(1) - y(n_Titik) * x(1))
      area = abs(area1) / 2.0_dp

      min_Y = minval(y)
      max_Y = maxval(y)
      Y_Step = int(max_Y - min_Y)

      allocate(Y_New(Y_Step+1))
      allocate(X_New(Y_Step+1))

      do i = 0, Y_Step
          Y_New(i+1) = min_Y + i  ! Увеличиваем Y на 1 метр
      end do

      ! Интерполяция X_new
      do i = 1, Y_Step
          if (Y_New(i) >= min_Y .and. Y_New(i) <= max_Y) then
              do j = 1, n_Titik - 1
                  if (Y_New(i) >= y(j) .and. Y_New(i) <= y(j + 1)) then
                      X_New(i) = x(j) + (x(j + 1) - x(j)) * (Y_New(i) - y(j)) / (y(j + 1) - y(j))
                      exit
                  end if
              end do 
          end if
      end do

      ! Вывод результатов
      print *, "Penampang", n_Penampang
      do i = 1, n_Titik
          print *, "Koordinat (x, y, z): ", x(i), y(i), z(i)
      end do
      do i = 1, Y_Step
          print *, "Hasil Interpolasi Kedalaman", Y_New(i), "m :", X_New(i), Y_New(i)
      end do
      print *, "Luas Penampang: ", area

      deallocate(x, y, z, Y_New, X_New)
  end do
  close(10)
end program Read_Cross

Пояснение изменений:

  1. Изменение логики цикла:

    • Вместо того чтобы проверять каждую пару точек, мы теперь проходим по массиву Y_New и используем вложенный цикл для нахождения соответствующих точек X для каждого уровня глубины.
  2. Оптимизация выделения памяти:

    • Обратите внимание, что массивы Y_New и X_New выделяются с размером Y_Step + 1, чтобы учесть все 1-метровые шаги.

С помощью этих корректировок ваш код будет более эффективным и будет корректно вычислять площадь поперечных сечений для различных уровней воды, при этом интерполируя значения глубины.

Вывод

Теперь программа должна работать с вашими данными и корректно вычислять площади поперечных сечений, а также проводить интерполяцию для различных уровней воды. Надеюсь, это решит вашу проблему! Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их.

Оцените материал
Добавить комментарий

Капча загружается...