OGS
DiameterProfile.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
6#include <algorithm>
7#include <functional>
8#include <numbers>
9#include <vector>
10
11#include "BaseLib/Error.h"
12
13namespace ProcessLib
14{
15namespace HeatTransportBHE
16{
17namespace BHE
18{
20{
21 DiameterProfile(std::vector<double> bounds, std::vector<double> diams)
22 : section_boundaries(std::move(bounds)),
23 section_diameters(std::move(diams))
24 {
25 if (section_boundaries.empty() || section_diameters.empty())
26 {
27 OGS_FATAL("DiameterProfile: vectors must be non-empty.");
28 }
29 if (section_boundaries.size() != section_diameters.size())
30 {
31 OGS_FATAL(
32 "DiameterProfile: section_boundaries (size {:d}) and "
33 "section_diameters (size {:d}) must have the same size.",
34 section_boundaries.size(), section_diameters.size());
35 }
36 if (std::any_of(section_diameters.begin(), section_diameters.end(),
37 [](double d) { return d <= 0.0; }))
38 {
39 OGS_FATAL("DiameterProfile: all diameters must be positive.");
40 }
41 if (std::adjacent_find(section_boundaries.begin(),
43 std::greater_equal<>{}) !=
45 {
46 OGS_FATAL(
47 "DiameterProfile: section_boundaries must be strictly "
48 "increasing.");
49 }
50 }
51
55 std::vector<double> const section_boundaries;
56
60 std::vector<double> const section_diameters;
61
67 int getSectionIndex(double distance_from_wellhead) const;
68
72 double diameterAtDistance(double distance_from_wellhead) const
73 {
74 return section_diameters[getSectionIndex(distance_from_wellhead)];
75 }
76
80 double areaAtDistance(double distance_from_wellhead) const
81 {
82 return circleArea(diameterAtDistance(distance_from_wellhead));
83 }
84
88 double diameterAtSection(int const section_index) const
89 {
90 if (section_index < 0 ||
91 section_index >= static_cast<int>(section_diameters.size()))
92 {
93 OGS_FATAL("Invalid section index: {:d}", section_index);
94 }
95 return section_diameters[section_index];
96 }
97
101 double areaAtSection(int const section_index) const
102 {
103 return circleArea(diameterAtSection(section_index));
104 }
105
109 {
110 return static_cast<int>(section_diameters.size());
111 }
112
113private:
114 static double circleArea(double const diameter)
115 {
116 return std::numbers::pi * diameter * diameter / 4;
117 }
118};
119
120inline int DiameterProfile::getSectionIndex(double distance_from_wellhead) const
121{
122 if (distance_from_wellhead < section_boundaries.front())
123 {
124 OGS_FATAL(
125 "Distance from wellhead is negative or before first section: "
126 "{:g}",
127 distance_from_wellhead);
128 }
129
130 // Binary search to find the section.
131 // Find the first boundary that is greater than distance_from_wellhead.
132 auto it = std::upper_bound(section_boundaries.begin(),
133 section_boundaries.end(),
134 distance_from_wellhead);
135
136 // Move back one position to get the section containing this distance.
137 if (it != section_boundaries.begin())
138 {
139 --it;
140 }
141
142 return static_cast<int>(std::distance(section_boundaries.begin(), it));
143}
144} // namespace BHE
145} // namespace HeatTransportBHE
146} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
double diameterAtDistance(double distance_from_wellhead) const
Get diameter at a given distance from wellhead.
double diameterAtSection(int const section_index) const
Get diameter for a specific section.
double areaAtDistance(double distance_from_wellhead) const
Get cross-sectional area at a given distance from wellhead.
double areaAtSection(int const section_index) const
Get cross-sectional area for a specific section.
int getSectionIndex(double distance_from_wellhead) const
Find the section index for a given distance from wellhead. Uses binary search for O(log n) lookup.
int getNumberOfSections() const
Get the number of sections.
DiameterProfile(std::vector< double > bounds, std::vector< double > diams)
static double circleArea(double const diameter)