BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSIdealGas.hh
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#ifndef BDSIDEALGAS_H
19#define BDSIDEALGAS_H
20
21#include "BDSMaterials.hh"
22#include "BDSUtilities.hh"
23#include "BDSWarning.hh"
24
25#include "globals.hh" // geant4 globals / types
26
27#include <iomanip>
28#include <list>
29#include <map>
30#include <set>
31#include <vector>
32
40public:
41 const static G4double R;
42
43 template <typename Type>
44 static G4double CalculateDensityFromPressureTemperature(const std::list<G4String>& components,
45 const std::list<Type>& componentFractions,
46 G4double pressure,
47 G4double temperature) {
48
49 G4double averageMolarMass = CalculateAverageMolarMass(components, componentFractions);
50 G4double density = (pressure*averageMolarMass)/(R*temperature);
51
52 return density;
53 }
54
55 template <typename Type>
56 static G4double CalculateTemperatureFromPressureDensity(const std::list<G4String>& components,
57 const std::list<Type>& componentFractions,
58 G4double pressure,
59 G4double density) {
60
61 G4double averageMolarMass = CalculateAverageMolarMass(components, componentFractions);
62 G4double temperature = (pressure*averageMolarMass)/(R*density);
63
64 return temperature;
65 }
66
67 template <typename Type>
68 static G4double CalculatePressureFromTemperatureDensity(const std::list<G4String>& components,
69 const std::list<Type>& componentFractions,
70 G4double temperature,
71 G4double density) {
72
73 G4double averageMolarMass = CalculateAverageMolarMass(components, componentFractions);
74 G4double pressure = (density*R*temperature)/(averageMolarMass);
75
76 return pressure;
77 }
78
79 template <typename Type>
80 static G4double CalculateDensityFromNumberDensity(const std::list<G4String>& components,
81 const std::list<Type>& componentFractions,
82 G4double numberDensity) {
83
84 G4double averageMolarMass = CalculateAverageMolarMass(components, componentFractions);
85 G4double density = numberDensity*averageMolarMass/CLHEP::Avogadro;
86
87 return density;
88 }
89
90 template <typename Type>
91 static G4double CalculateDensityFromMolarDensity(const std::list<G4String>& components,
92 const std::list<Type>& componentFractions,
93 G4double molarDensity) {
94
95 G4double averageMolarMass = CalculateAverageMolarMass(components, componentFractions);
96 G4double density = molarDensity*averageMolarMass;
97
98 return density;
99 }
100
101 template <typename Type>
102 static G4double CalculateAverageMolarMass(const std::list<G4String>& components,
103 const std::list<Type>& componentFractions){
104
105 std::vector<G4String> componentsVector{ components.begin(), components.end() };
106 std::vector<Type> componentFractionsVector{ componentFractions.begin(), componentFractions.end() };
107 std::map<G4String, Type> componentsTable;
108
109 G4double averageMolarMass = 0;
110 G4double fracSum = 0;
111 for (size_t i=0; i < componentsVector.size(); i++)
112 {
113 const G4String& componentName = componentsVector[i];
114 auto component = BDSMaterials::Instance()->GetMaterial(componentName);
115
116 size_t nbelement = component->GetNumberOfElements();
117 if (nbelement == 1)
118 {
119 auto element = component->GetElement(0);
120 auto molarMass = element->GetN();
121 averageMolarMass = averageMolarMass + componentFractionsVector[i] * molarMass;
122 fracSum = fracSum + componentFractionsVector[i];
123 }
124 else
125 {
126 auto elementVector = component->GetElementVector();
127 std::list<G4String> elementNames;
128 std::list<Type> elementFractions;
129 for (const auto element: *elementVector)
130 {
131 elementNames.push_back(element->GetName());
132 }
133 for (size_t ii=0; ii < elementVector->size(); ii++)
134 {
135 elementFractions.push_back(component->GetFractionVector()[ii]);
136 }
137 averageMolarMass = averageMolarMass + componentFractionsVector[i] * CalculateAverageMolarMass(elementNames, elementFractions);
138 fracSum = fracSum + componentFractionsVector[i];
139 }
140 }
141
142 return averageMolarMass/fracSum;
143 }
144
145
146 template <typename Type>
147 static void CheckGasLaw(G4String name,
148 G4double &temperature,
149 G4double &pressure,
150 G4double &density,
151 const std::list<G4String>& components,
152 const std::list<Type>& componentFractions) {
153
154#ifdef BDSDEBUG
155 G4cout << "BDSIdealGas::CheckGasLaw: " << G4endl;
156#endif
157 if (density != 0 && pressure == 0)
158 {
159 G4double calcPressure = CalculatePressureFromTemperatureDensity(components, componentFractions,
160 temperature, density);
161 pressure = calcPressure;
162 G4String msg = "BDSIdealGas :: Computing pressure " + std::to_string(calcPressure);
163 msg += " atmosphere for material " + name;
164 BDS::Warning(msg);
165 }
166
167 else if (density !=0 && pressure !=0 && temperature == 300)
168 {
169 G4double calcTemp = CalculateTemperatureFromPressureDensity(components, componentFractions,
170 pressure, density);
171 temperature = calcTemp;
172 G4String msg = "BDSIdealGas :: Computing temperature " + std::to_string(calcTemp);
173 msg += " kelvin for material " + name;
174 BDS::Warning(msg);
175 }
176
177 else if (density == 0 && pressure !=0)
178 {
179 G4double calcDens = CalculateDensityFromPressureTemperature(components, componentFractions,
180 pressure, temperature);
181 density = calcDens;
182 G4String msg = "BDSIdealGas :: Computing density " + std::to_string(calcDens);
183 msg += " g.cm-3 for material " + name;
184 BDS::Warning(msg);
185 }
186
187 else if (density !=0 && pressure !=0 && temperature != 300)
188 {
189 G4double calcDensity = CalculateDensityFromPressureTemperature(components, componentFractions, pressure, temperature);
190 if(density != calcDensity)
191 {
192 G4String msg = "Ideal gas density calculated from pressure and temperature doesn't match given density\n";
193 msg += "Assuming temperature of 300K and computing correct pressure for this density";
194 BDS::Warning(msg);
195 temperature = 300;
196 pressure = CalculatePressureFromTemperatureDensity(components, componentFractions, temperature, density);
197 }
198 }
199 }
200};
201
202const G4double BDSIdealGas::R = CLHEP::Avogadro * CLHEP::k_Boltzmann / CLHEP::joule * 10; //TODO find out about this factor
203
204#endif
A class to perform ideal gas calculations.
static BDSMaterials * Instance()
Singleton pattern access.
G4Material * GetMaterial(G4String material) const
Get material by name.