gsystem
Loading...
Searching...
No Matches
gmaterial.cc
Go to the documentation of this file.
1
7
8#include "gutilities.h"
9//using namespace gutilities;
10
11
12// gsystem
13#include "gmaterial.h"
14#include "gsystemConventions.h"
15
16// c++
17#include <iostream>
18#include <sstream>
19
20
21GMaterial::GMaterial(const std::string &s, std::vector<std::string> pars,
22 const std::shared_ptr<GLogger> &logger) : GBase(logger),
23 system(s) {
24 if (pars.size() != gsystem::GMATERIALNUMBEROFPARS &&
25 pars.size() != gsystem::GMATERIALNUMBEROFPARS + 4) {
26 log->error(
27 gsystem::ERR_GWRONGNUMBEROFPARS,
28 "Incorrect number of material parameters for %1. Expected %2 but we got %3", pars[0],
29 gsystem::GMATERIALNUMBEROFPARS, pars.size());
30 } else {
31 // The parameter vector is a serialized DB/ASCII row. Parsing is positional.
32 size_t i = 0;
33
34 name = gutilities::removeAllSpacesFromString(pars[i++]);
35 density = stod(gutilities::removeAllSpacesFromString(pars[i++]));
36
37 // The "composition" field is tokenized into (component, amount) pairs.
38 setComponentsFromString(pars[i++]);
39
40 // Human-readable description (kept verbatim).
41 description = pars[i++];
42
43 // Optical properties: serialized null fields are skipped at this input boundary.
44 getMaterialPropertyFromString(pars[i++], "photonEnergy");
45 getMaterialPropertyFromString(pars[i++], "indexOfRefraction");
46 getMaterialPropertyFromString(pars[i++], "absorptionLength");
47 getMaterialPropertyFromString(pars[i++], "reflectivity");
48 getMaterialPropertyFromString(pars[i++], "efficiency");
49
50 // Scintillation properties (spectra first, then scalars).
51 getMaterialPropertyFromString(pars[i++], "fastcomponent");
52 getMaterialPropertyFromString(pars[i++], "slowcomponent");
53
54 // assign_if_set increment index
55 scintillationyieldSet = assign_if_set(pars, i, scintillationyield);
56 resolutionscaleSet = assign_if_set(pars, i, resolutionscale);
57 fasttimeconstantSet = assign_if_set(pars, i, fasttimeconstant);
58 slowtimeconstantSet = assign_if_set(pars, i, slowtimeconstant);
59 yieldratioSet = assign_if_set(pars, i, yieldratio);
60 birksConstantSet = assign_if_set(pars, i, birksConstant);
61
62 // Other optical processes: the final vector load triggers cross-vector size validation.
63 getMaterialPropertyFromString(pars[i++], "rayleigh");
64 if (i < pars.size()) {
65 getMaterialPropertyFromString(pars[i++], "mie");
66 mieforwardSet = assign_if_set(pars, i, mieforward);
67 miebackwardSet = assign_if_set(pars, i, miebackward);
68 mieratioSet = assign_if_set(pars, i, mieratio);
69 }
70 }
71}
72
73
74std::ostream &operator<<(std::ostream &stream, const GMaterial &gMat) {
75 stream << std::endl;
76 stream << " - Material: " << gMat.name << " in system " << gMat.system << ": " << std::endl;
77 stream << " Density: " << gMat.density << std::endl;
78 if (!gMat.components.empty()) {
79 stream << " Composition: " << std::endl;
80 for (unsigned m = 0; m < gMat.components.size(); m++) {
81 std::string quantity = gMat.amounts[m] > 1 ? " atoms " : " fractional mass";
82 stream << " ・ " << gMat.components[m] << quantity << " " << gMat.amounts[m] << std::endl;
83 }
84 }
85 stream << " Description: " << gMat.description << std::endl;
86 stream << std::endl;
87
88 return stream;
89}
90
91
92// sets components and amounts
93void GMaterial::setComponentsFromString(const std::string &composition) {
94 std::vector<std::string> allComponents = gutilities::getStringVectorFromString(composition);
95
96 // Interpret alternating tokens as (component, amount) pairs.
97 for (unsigned e = 0; e < allComponents.size() / 2; e++) {
98 components.push_back(allComponents[e * 2]);
99 amounts.push_back(stod(allComponents[e * 2 + 1]));
100 }
101}
102
103
104// load property from DB entry based on its name
105void GMaterial::getMaterialPropertyFromString(const std::string &parameter, const std::string &propertyName) {
106 // Nothing to do if the parameter is not assigned.
108 return;
109 }
110
111 // Tokenize the string and parse each component to a numeric value with units.
112 std::stringstream parameterComponents(parameter);
113
114 while (!parameterComponents.eof()) {
115 std::string component;
116 parameterComponents >> component;
117
118 // Removing whitespaces.
119 std::string trimmedComponent = gutilities::removeLeadingAndTrailingSpacesFromString(component);
120 // Non set properties
121
122 // Vector-valued properties append one value per token.
123 if (propertyName == "photonEnergy") {
124 photonEnergy.push_back(gutilities::getG4Number(trimmedComponent));
125 } else if (propertyName == "indexOfRefraction") {
126 indexOfRefraction.push_back(gutilities::getG4Number(trimmedComponent));
127 } else if (propertyName == "absorptionLength") {
128 absorptionLength.push_back(gutilities::getG4Number(trimmedComponent));
129 } else if (propertyName == "reflectivity") {
130 reflectivity.push_back(gutilities::getG4Number(trimmedComponent));
131 } else if (propertyName == "efficiency") {
132 efficiency.push_back(gutilities::getG4Number(trimmedComponent));
133 } else if (propertyName == "fastcomponent") {
134 fastcomponent.push_back(gutilities::getG4Number(trimmedComponent));
135 } else if (propertyName == "slowcomponent") {
136 slowcomponent.push_back(gutilities::getG4Number(trimmedComponent));
137 }
138 // Scalar-valued properties overwrite with the last parsed token.
139 else if (propertyName == "scintillationyield") {
140 scintillationyield = gutilities::getG4Number(trimmedComponent);
141 } else if (propertyName == "resolutionscale") {
142 resolutionscale = gutilities::getG4Number(trimmedComponent);
143 } else if (propertyName == "fasttimeconstant") {
144 fasttimeconstant = gutilities::getG4Number(trimmedComponent);
145 } else if (propertyName == "slowtimeconstant") {
146 slowtimeconstant = gutilities::getG4Number(trimmedComponent);
147 } else if (propertyName == "yieldratio") {
148 yieldratio = gutilities::getG4Number(trimmedComponent);
149 } else if (propertyName == "mie") {
150 mie.push_back(gutilities::getG4Number(trimmedComponent));
151 } else if (propertyName == "rayleigh") {
152 rayleigh.push_back(gutilities::getG4Number(trimmedComponent));
153 }
154 }
155
156 // Validation runs once, after all tokens for this property have been parsed.
157 // Rayleigh is loaded last, so every other optical vector is fully populated and can be
158 // cross-checked against photonEnergy here. (Running this inside the token loop fired on
159 // the very first rayleigh value, before the vector was complete.)
160 if (propertyName == "rayleigh" || propertyName == "mie") {
161 // Rayleigh is loaded last: at this point we can validate that all other optical vectors
162 // either are empty (not specified) or match the photonEnergy vector length.
163 //
164 // If they do not match, behavior is undefined because properties would be evaluated
165 // at inconsistent energy grids.
166 unsigned long photonEnergyVectorSize = photonEnergy.size();
167
168 if (!indexOfRefraction.empty() && indexOfRefraction.size() != photonEnergyVectorSize) {
169 log->error(
171 "indexOfRefraction size %1 mismatch: photonEnergy has size %2", indexOfRefraction.size(),
172 photonEnergyVectorSize);
173 }
174 if (!absorptionLength.empty() && absorptionLength.size() != photonEnergyVectorSize) {
175 log->error(
177 "absorptionLength size %1 mismatch: photonEnergy has size %2", absorptionLength.size(),
178 photonEnergyVectorSize);
179 }
180 if (!reflectivity.empty() && reflectivity.size() != photonEnergyVectorSize) {
181 log->error(
183 "reflectivity size %1 mismatch: photonEnergy has size %2", reflectivity.size(),
184 photonEnergyVectorSize);
185 }
186 if (!efficiency.empty() && efficiency.size() != photonEnergyVectorSize) {
187 log->error(
189 "efficiency size %1 mismatch: photonEnergy has size %2", efficiency.size(),
190 photonEnergyVectorSize);
191 }
192 if (!fastcomponent.empty() && fastcomponent.size() != photonEnergyVectorSize) {
193 log->error(
195 "fastcomponent size %1 mismatch: photonEnergy has size %2", fastcomponent.size(),
196 photonEnergyVectorSize);
197 }
198 if (!slowcomponent.empty() && slowcomponent.size() != photonEnergyVectorSize) {
199 log->error(
201 "slowcomponent size %1 mismatch: photonEnergy has size %2", slowcomponent.size(),
202 photonEnergyVectorSize);
203 }
204 if (!mie.empty() && mie.size() != photonEnergyVectorSize) {
206 "Mie size %1 mismatch: photonEnergy has size %2", mie.size(), photonEnergyVectorSize);
207 }
208 if (!rayleigh.empty() && rayleigh.size() != photonEnergyVectorSize) {
209 log->error(
211 "rayleigh size %1 mismatch: photonEnergy has size %2", rayleigh.size(), photonEnergyVectorSize);
212 }
213 }
214}
215
216
217bool GMaterial::assign_if_set(const std::vector<std::string> &pars, size_t &i, double &out) {
218 if (i >= pars.size()) return false;
219
220 const std::string trimmed =
222
223 std::string_view sv(trimmed);
224 if (gutilities::is_unset(sv)) return false;
225
226 try {
227 out = std::stod(trimmed);
228 return true;
229 } catch (const std::exception &) {
230 // Do not error here: malformed optional scalars are treated as "not set".
231 return false;
232 }
233}
GBase(const std::shared_ptr< GOptions > &gopt, std::string logger_name="")
std::shared_ptr< GLogger > log
GMaterial(const std::string &system, std::vector< std::string > pars, const std::shared_ptr< GLogger > &logger)
Construct a material from a serialized parameter list.
Definition gmaterial.cc:21
std::ostream & operator<<(std::ostream &stream, const GMaterial &gMat)
Definition gmaterial.cc:74
Conventions and shared constants for the detector-system module.
constexpr int ERR_GMATERIALOPTICALPROPERTYMISMATCH
constexpr int GMATERIALNUMBEROFPARS
Number of database parameters defining a gmaterial entry.
double getG4Number(const string &v, bool warnIfNotUnit=false)
bool is_unset(std::string_view s)
string removeLeadingAndTrailingSpacesFromString(const std::string &input)
vector< std::string > getStringVectorFromString(const std::string &input)