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