Вопрос или проблема
Итак, я хочу рассчитать сеченую площадь реки с неправильным руслом, а также рассчитать сеченую площадь для каждого 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 и в целом имеет правильную структуру. Однако, есть несколько моментов, которые необходимо улучшить, чтобы он выполнял поставленные задачи более эффективно.
Корректировки
-
Цикл для интерполяции глубины:
- В текущем коде не предусмотрено, что вы будете проводить интерполяцию между всеми парами (x, y) для каждого 1 метра от минимального до максимального y.
-
Исправление логики интерполяции:
- Вместо проверки на
if ((Y_New(i) > y(i)).and.(Y_New(i) < y(i + 1)))
, лучше использовать цикл, который проверяет все точки на наличие текущего значенияY_New
, чтобы оно не выходило за пределы массиваY
.
- Вместо проверки на
-
Динамическое выделение памяти:
- Убедитесь, что память для массивов
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
Пояснение изменений:
-
Изменение логики цикла:
- Вместо того чтобы проверять каждую пару точек, мы теперь проходим по массиву
Y_New
и используем вложенный цикл для нахождения соответствующих точек X для каждого уровня глубины.
- Вместо того чтобы проверять каждую пару точек, мы теперь проходим по массиву
-
Оптимизация выделения памяти:
- Обратите внимание, что массивы Y_New и X_New выделяются с размером
Y_Step + 1
, чтобы учесть все 1-метровые шаги.
- Обратите внимание, что массивы Y_New и X_New выделяются с размером
С помощью этих корректировок ваш код будет более эффективным и будет корректно вычислять площадь поперечных сечений для различных уровней воды, при этом интерполируя значения глубины.
Вывод
Теперь программа должна работать с вашими данными и корректно вычислять площади поперечных сечений, а также проводить интерполяцию для различных уровней воды. Надеюсь, это решит вашу проблему! Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их.