6 #include "../icedb/refract/refract.hpp" 7 #include "../icedb/refract/refractBase.hpp" 8 #include "../icedb/zeros.hpp" 9 #include "../icedb/units/units.hpp" 10 #include "../icedb/error.hpp" 11 #include "../icedb/logging.hpp" 15 namespace implementations {
22 std::lock_guard<std::mutex> lock(m_refracts);
23 static bool inited =
false;
27 std::shared_ptr<std::map<std::string, provider_p> > data(
28 new std::map<std::string, provider_p>);
31 "mWaterLiebe",
"water",
32 "Liebe, H.J., Hufford, G.A. & Manabe, T. Int J Infrared Milli Waves (1991) 12: 659. doi:10.1007/BF01008897",
35 ->addReq(
"spec",
"GHz", 0, 1000)->addReq(
"temp",
"K", 273.15, 373.15)->registerFunc();
37 "mWaterFreshMeissnerWentz",
"water",
38 "T. Meissner and F. J. Wentz, \"The complex dielectric constant of pure and sea water from microwave satellite observations\", IEEE Trans. Geosci. Remote Sensing, vol. 42, no.9, pp. 1836-1849, September 2004.",
39 "For pure water (no salt)",
41 ->addReq(
"spec",
"GHz", 0, 500)->addReq(
"temp",
"K", 253.15, 313.15)->registerFunc();
44 "Thermal Microwave Radiation: Applications for Remote Sensing, " 45 "Chapter 5, Microwave dielectric properties of ice, " 46 "By Christian Matzler(2006)",
49 ->addReq(
"spec",
"GHz", 0, 1000)->addReq(
"temp",
"K", 0, 273.15)->registerFunc();
52 "Stephen G. Warren, \"Optical constants of ice from the ultraviolet to the microwave, \" Appl. Opt. 23, 1206-1225 (1984)",
55 ->addReq(
"spec",
"GHz", 0.167, 8600)->addReq(
"temp",
"degC", -60, -1)->registerFunc();
57 "mWaterHanel",
"water",
58 "Tables from Thomas Hanel. Not sure which paper.",
"",
60 ->addReq(
"spec",
"um", 0.2, 30000)->registerFunc(100);
63 "Tables from Thomas Hanel. Not sure which paper.",
"",
65 ->addReq(
"spec",
"um", 0.2, 30000)->registerFunc(100);
69 "Tables from Thomas Hanel. Not sure which paper.",
"",
71 ->addReq(
"spec",
"um", 0.2, 30000)->registerFunc(100);
73 "mSeaSaltHanel",
"SeaSalt",
74 "Tables from Thomas Hanel. Not sure which paper.",
"",
76 ->addReq(
"spec",
"um", 0.2, 30000)->registerFunc(100);
79 "Tables from Thomas Hanel. Not sure which paper.",
"",
81 ->addReq(
"spec",
"um", 0.2, 300)->registerFunc(100);
83 "mSandOHanel",
"Sand_O",
84 "Tables from Thomas Hanel. Not sure which paper.",
"",
86 ->addReq(
"spec",
"um", 0.2, 300)->registerFunc(100);
88 "mSandEHanel",
"Sand_E",
89 "Tables from Thomas Hanel. Not sure which paper.",
"",
91 ->addReq(
"spec",
"um", 0.2, 300)->registerFunc(100);
98 const std::string &name,
const std::string &subst,
99 const std::string &source,
const std::string ¬es,
103 res->substance = subst;
104 res->source = source;
106 res->speciality_function_type = sv;
107 res->specialty_pointer = ptr;
111 double low,
double high) {
112 auto res = this->shared_from_this();
126 block->insert(std::pair<int,provider_mp>(priority,res));
135 const std::string &name,
const std::string& units,
136 double low,
double high) {
138 res->parameterName = name;
139 res->parameterUnits = units;
140 res->hasValidRange =
true;
141 res->validRange = std::pair<double, double>(low, high);
160 .add<std::string>(
"Reason",
"No provider was passed to this function - instead, a NULL was passed!");
161 out <<
"Provider:\t" << p->name <<
"\n" 162 <<
"\tSubstance:\t" << p->substance <<
"\n" 163 <<
"\tSource:\t" << p->source <<
"\n" 164 <<
"\tNotes:\t" << p->notes <<
"\n";
165 if (p->reqs.size()) {
166 out <<
"\tRequirements:\n";
167 for (
const auto &r : p->reqs) {
168 out <<
"\t\tParameter:\t" << r.first
169 <<
"\t\t\tRange:\t" << r.second->validRange.first <<
" to " 170 << r.second->validRange.second <<
" " 171 << r.second->parameterUnits <<
"\n";
177 .add<std::string>(
"Reason",
"The pointer passed to this function was NULL!");
178 if (p->size() == 1) out <<
"Providers found: 1\n";
179 else out <<
"Providers enumerated: " << p->size() <<
"\n";
180 for (
const auto &i : *(p.get())) {
186 out <<
"Substances:" << std::endl;
188 out <<
"\t" << i << std::endl;
203 bool haveFreq,
bool haveTemp,
const std::string & start) {
210 if ((cres->reqs.count(
"spec") && !haveFreq) || (cres->reqs.count(
"temp") && !haveTemp)) {
212 .add<std::string>(
"Reason",
"Attempting to find the provider for a manually-" 213 "specified refractive index formula, but the retrieved formula's " 214 "requirements do not match what whas passed.")
215 .add<std::string>(
"Provider", subst);
222 bool startSearch =
false;
223 if (start ==
"") startSearch =
true;
224 for (
const auto &p : *(pss.get())) {
226 if (p.second->name == start) startSearch =
true;
229 if (p.second->reqs.count(
"spec") && !haveFreq)
continue;
230 if (p.second->reqs.count(
"temp") && !haveTemp)
continue;
237 bool haveFreq,
bool haveTemp) {
244 if ((cres->reqs.count(
"spec") && !haveFreq) || (cres->reqs.count(
"temp") && !haveTemp)) {
246 .add<std::string>(
"Reason",
"Attempting to find the provider for a manually-" 247 "specified refractive index formula, but the retrieved formula's " 248 "requirements do not match what was passed.")
249 .add<bool>(
"Have-Freq", haveFreq)
250 .add<
bool>(
"Need-Freq", (bool) cres->reqs.count(
"spec"))
251 .add<bool>(
"Have-Temp", haveTemp)
252 .add<
bool>(
"Need-Temp", (bool)cres->reqs.count(
"temp"))
253 .add<std::string>(
"Provider", subst);
255 res->insert(std::pair<int, provider_p>(0, cres));
261 for (
const auto &p : *(pss.get())) {
262 if (p.second->reqs.count(
"spec") && !haveFreq)
continue;
263 if (p.second->reqs.count(
"temp") && !haveTemp)
continue;
271 auto compatFunc = [](
275 std::complex<double> &m) ->
void {
277 void(*transFunc)(double, std::complex<double>&) = (
void(*)(double,std::complex<double>&))innerFunc;
279 transFunc(inSpec, m);
281 transFunc(converterFreq->convert(inSpec), m);
287 .add<std::string>(
"Reason",
"You called the wrong prepRefract.");
288 if (!prov->reqs.count(
"spec"))
290 .add<std::string>(
"Reason",
"Attempting to prepare a refractive index formula that does not " 291 "require a frequency / wavelength / wavenumber, but one was provided.");
292 std::string reqUnits = prov->reqs.at(
"spec")->parameterUnits;
293 if (reqUnits != inFreqUnits)
296 res = std::bind(compatFunc,
298 prov->specialty_pointer,
299 std::placeholders::_1,
300 std::placeholders::_2);
303 const std::string &inFreqUnits,
const std::string &inTempUnits,
306 auto compatFunc = [](
312 std::complex<double> &m) ->
void {
314 void(*transFunc)(double, double, std::complex<double>&) = (
void(*)(double, double, std::complex<double>&))innerFunc;
315 if (!converterFreq && !converterTemp)
316 transFunc(inSpec, inTemp, m);
317 else if (converterFreq && !converterTemp)
318 transFunc(converterFreq->convert(inSpec), inTemp, m);
319 else if (!converterFreq && converterTemp)
320 transFunc(inSpec, converterTemp->convert(inTemp), m);
321 else transFunc(converterFreq->convert(inSpec), converterTemp->convert(inTemp), m);
326 .add<std::string>(
"Reason",
"You called the wrong prepRefract.");
327 if (!prov->reqs.count(
"spec"))
329 .add<std::string>(
"Reason",
"Attempting to prepare a refractive index formula that does not " 330 "require a frequency / wavelength / wavenumber, but one was provided.");
331 std::string reqFreqUnits = prov->reqs.at(
"spec")->parameterUnits;
332 if (reqFreqUnits != inFreqUnits)
335 if (!prov->reqs.count(
"temp"))
337 .add<std::string>(
"Reason",
"Attempting to prepare a refractive index formula that does not " 338 "require a temperature, but one was provided.");
339 std::string reqTempUnits = prov->reqs.at(
"temp")->parameterUnits;
340 if (reqTempUnits != inTempUnits)
343 res = std::bind(compatFunc,
346 prov->specialty_pointer,
347 std::placeholders::_1,
348 std::placeholders::_2,
349 std::placeholders::_3);
353 void bruggeman(std::complex<double> Ma, std::complex<double> Mb,
354 double fa, std::complex<double> &Mres)
357 complex<double> eA, eB, eRes;
363 auto formula = [&](std::complex<double> x) -> std::complex<double>
367 complex<double> res, pa, pb;
368 pa = complex<double>(fa, 0) * (eA - x) / (eA + (complex<double>(2., 0)*x));
369 pb = complex<double>(1. - fa, 0) * (eB - x) / (eB + (complex<double>(2., 0)*x));
374 complex<double> gA(1.0, 1.0), gB(1.55, 1.45);
379 "bruggeman code called\n\tMa " << Ma <<
"\n\tMb " << Mb <<
"\n\tfa " << fa
380 <<
"\n\tMres " << Mres);
383 void debyeDry(std::complex<double> Ma, std::complex<double> Mb,
384 double fa, std::complex<double> &Mres)
387 std::complex<double> eA, eB, eRes;
391 complex<double> pa = fa * (eA - complex<double>(1., 0)) / (eA + complex<double>(2., 0));
392 complex<double> pb = (1. - fa) * (eB - complex<double>(1., 0)) / (eB + complex<double>(2., 0));
394 complex<double> fact = pa + pb;
395 eRes = (complex<double>(2., 0) * fact + complex<double>(1., 0))
396 / (complex<double>(1., 0) - fact);
399 "debyeDry code called\n\tMa " << Ma <<
"\n\tMb " << Mb <<
"\n\tfa " << fa
400 <<
"\n\tMres " << Mres);
404 double fa, std::complex<double> &Mres)
407 std::complex<double> eA, eB, eRes;
413 complex<double> a = complex<double>(fa, 0) * (eA - eB) / (eA + (complex<double>(2, 0) * eB));
414 eRes = eB * (complex<double>(2, 0) * a + complex<double>(1, 0))
415 / (complex<double>(1, 0) - a);
418 "maxwellGarnettSpheres code called\n\tMa " << Ma <<
"\n\tMb " << Mb <<
"\n\tfa " << fa
419 <<
"\n\tMres " << Mres);
423 double fa, std::complex<double> &Mres)
426 std::complex<double> eA, eB, eRes;
430 complex<double> betaA = complex<double>(2., 0)*eA / (eB - eA);
431 complex<double> betaB = ((eB / (eB - eA)) * log(eB / eA)) - complex<double>(1., 0);
432 complex<double> beta = betaA * betaB;
434 complex<double> cf(fa, 0), cfc(1. - fa, 0);
436 eRes = ((cfc*beta) + (cf*eA)) / (cf + (cfc*beta));
439 "maxwellGarnettEllipsoids code called\n\tMa " << Ma <<
"\n\tMb " << Mb <<
"\n\tfa " << fa
440 <<
"\n\tMres " << Mres);
443 void sihvola(std::complex<double> Ma, std::complex<double> Mb,
444 double fa,
double nu, std::complex<double> &Mres)
447 std::complex<double> eA, eB, eRes;
458 auto formulaSihvola = [&](std::complex<double> x) -> std::complex<double>
461 complex<double> res, pa, pb;
462 pa = (x - eB) / (x + (complex<double>(2.0, 0)*eB) + (complex<double>(nu, 0)*(x - eB)));
463 pb = complex<double>(fa, 0) *
464 (eA - eB) / (eA + (complex<double>(2.0, 0)*eB) + (complex<double>(nu, 0)*(x - eB)));
469 complex<double> gA(1.0, 1.0), gB(1.55, 1.45);
473 <<
"\n\tnu " << nu <<
"\n\tMres " << Mres);
476 std::complex<double>
mToE(std::complex<double> m)
480 void mToE(std::complex<double> m, std::complex<double> &e)
485 std::complex<double>
eToM(std::complex<double> e)
489 void eToM(std::complex<double> e, std::complex<double> &m)
494 double guessTemp(
double freq,
const std::complex<double>& m,
495 std::function<
void(
double freq,
double temp, std::complex<double>& mres)> meth,
496 double TA,
double TB)
500 auto formulaTemp = [&](
double T) ->
double 504 complex<double> mRes;
507 double mNorm = mRes.real() - m.real();
std::complex< double > eToM(std::complex< double > e)
void mIceWarren(double f, double t, std::complex< double > &m)
Ice complex refractive index for microwave/uv.
void mWaterHanel(double lambda, std::complex< double > &m)
Water complex refractive index for ir/vis.
void mIceMatzler(double f, double t, std::complex< double > &m)
std::map< std::string, provider_mp > providersByName
void enumSubstances(std::ostream &out)
void enumProviders(all_providers_p p, std::ostream &out)
U secantMethod(const T &f, U guess_a, U guess_b, double eps=0.000001, size_t maxIter=50)
double guessTemp(double freq, const std::complex< double > &m, std::function< void(double freq, double temp, std::complex< double > &mres)> meth, double TA, double TB)
void mNaClHanel(double lambda, std::complex< double > &m)
Sodium chloride refractive index for ir/vis.
void sihvola(std::complex< double > Ma, std::complex< double > Mb, double fa, double nu, std::complex< double > &Mres)
void mSandEHanel(double lambda, std::complex< double > &m)
Sand E-ray refractive index for ir/vis (birefringent)
void maxwellGarnettSpheres(std::complex< double > Ma, std::complex< double > Mb, double fa, std::complex< double > &Mres)
void enumProvider(provider_p p, std::ostream &out)
void mSandOHanel(double lambda, std::complex< double > &m)
Sand O-ray refractvie index for ir/vis (birefringent)
all_providers_p listAllProviders()
std::function< void(double, double, std::complex< double > &)> refractFunction_freq_temp_t
provider_mp registerFunc(int priority=0)
std::shared_ptr< const requirement_s > requirement_p
std::shared_ptr< provider_s > provider_mp
void prepRefract(provider_p prov, const std::string &inFreqUnits, refractFunction_freqonly_t &res)
static requirement_p generate(const std::string &name, const std::string &units, double low, double high)
all_providers_p findProviders(const std::string &subst, bool haveFreq, bool haveTemp)
void maxwellGarnettEllipsoids(std::complex< double > Ma, std::complex< double > Mb, double fa, std::complex< double > &Mres)
std::shared_ptr< const provider_collection_type > all_providers_p
provider_mp addReq(const std::string &name, const std::string &units, double low, double high)
static std::shared_ptr< const converter > generate(const std::string &inUnits, const std::string &outUnits)
static std::shared_ptr< const converter > generate(const std::string &inUnits, const std::string &outUnits)
provider_p findProviderByName(const std::string &providerName)
provider_p findProvider(const std::string &subst, bool haveFreq, bool haveTemp, const std::string &start)
void mDustHanel(double lambda, std::complex< double > &m)
Dust-like particle refractive index for ir/vis.
std::shared_ptr< const provider_s > provider_p
void debyeDry(std::complex< double > Ma, std::complex< double > Mb, double fa, std::complex< double > &Mres)
std::function< void(double, std::complex< double > &)> refractFunction_freqonly_t
std::multimap< int, provider_p > provider_collection_type
std::map< std::string, all_providers_mp > providersSet
void mWaterLiebe(double f, double t, std::complex< double > &m)
void mWaterFreshMeissnerWentz(double f, double t, std::complex< double > &m)
void bruggeman(std::complex< double > Ma, std::complex< double > Mb, double fa, std::complex< double > &Mres)
std::shared_ptr< provider_collection_type > all_providers_mp
#define ICEDB_log(c, p, x)
all_providers_mp allProvidersSet
static provider_mp generate(const std::string &name, const std::string &subst, const std::string &source, const std::string ¬es, provider_s::spt sv, void *ptr)
void mIceHanel(double lambda, std::complex< double > &m)
Ice complex refractive index for ir/vis.
std::complex< double > mToE(std::complex< double > m)
m to e converters
void mSeaSaltHanel(double lambda, std::complex< double > &m)
Sea salt refractive index for ir/vis.
std::shared_ptr< const converter > converter_p
std::set< std::string > substs