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