|
|
|
@ -178,10 +178,10 @@ std::pair<const BaseParameters*, MString> LayeredData::Parameters(michlib_intern
|
|
|
|
|
return {ppar.release(), ""}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LayeredData::Data LayeredData::Read(const MString& vname, const BaseParameters* ip, size_t i) const |
|
|
|
|
bool LayeredData::Read(const MString& vname, std::map<MString, LayeredData::Data>& cache, const BaseParameters* ip, size_t i) const |
|
|
|
|
{ |
|
|
|
|
if(!isOk()) return Data(); |
|
|
|
|
bool nodepth = false; |
|
|
|
|
if(cache.contains(vname)) return true; |
|
|
|
|
if(!isOk()) return false; |
|
|
|
|
|
|
|
|
|
auto p = dynamic_cast<const struct Parameters*>(ip); |
|
|
|
|
auto [name, id, tid] = VarNameLoc(vname, times[i]); |
|
|
|
@ -190,86 +190,101 @@ LayeredData::Data LayeredData::Read(const MString& vname, const BaseParameters*
|
|
|
|
|
// ptemp from temp and sal
|
|
|
|
|
if(vname == "ptemp") |
|
|
|
|
{ |
|
|
|
|
auto temp = Read("temp", ip, i); |
|
|
|
|
auto sal = Read("sal", ip, i); |
|
|
|
|
if(!(temp && sal)) return Data(); |
|
|
|
|
temp.SetUnit("degrees_C"); |
|
|
|
|
for(size_t ind = 0; ind < temp.N(); ind++) |
|
|
|
|
if(!(Read("temp", cache, ip, i) && Read("sal", cache, ip, i))) return false; |
|
|
|
|
cache[vname] = cache.at("temp").CopyGrid(); |
|
|
|
|
auto& ptemp = cache.at(vname); |
|
|
|
|
const auto& temp = cache.at("temp"); |
|
|
|
|
const auto& sal = cache.at("sal"); |
|
|
|
|
ptemp.SetUnit("degrees_C"); |
|
|
|
|
for(size_t ind = 0; ind < ptemp.N(); ind++) |
|
|
|
|
{ |
|
|
|
|
if(temp.IsFill(ind) || sal.IsFill(ind)) |
|
|
|
|
temp.V(ind) = temp.Fillval(); |
|
|
|
|
ptemp.V(ind) = ptemp.Fillval(); |
|
|
|
|
else |
|
|
|
|
temp.V(ind) = Temp2PTemp(temp.V(ind), sal.V(ind), Depth(p->layer), temp.Lon(ind), temp.Lat(ind)); |
|
|
|
|
ptemp.V(ind) = Temp2PTemp(temp.V(ind), sal.V(ind), Depth(p->layer), ptemp.Lon(ind), ptemp.Lat(ind)); |
|
|
|
|
} |
|
|
|
|
return temp; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
// temp from ptemp and sal
|
|
|
|
|
if(vname == "temp") |
|
|
|
|
{ |
|
|
|
|
auto temp = Read("ptemp", ip, i); |
|
|
|
|
auto sal = Read("sal", ip, i); |
|
|
|
|
if(!(temp && sal)) return Data(); |
|
|
|
|
if(!(Read("ptemp", cache, ip, i) && Read("sal", cache, ip, i))) return false; |
|
|
|
|
cache[vname] = cache.at("ptemp").CopyGrid(); |
|
|
|
|
auto& temp = cache.at(vname); |
|
|
|
|
const auto& ptemp = cache.at("ptemp"); |
|
|
|
|
const auto& sal = cache.at("sal"); |
|
|
|
|
temp.SetUnit("degrees_C"); |
|
|
|
|
for(size_t ind = 0; ind < temp.N(); ind++) |
|
|
|
|
{ |
|
|
|
|
if(temp.IsFill(ind) || sal.IsFill(ind)) |
|
|
|
|
if(ptemp.IsFill(ind) || sal.IsFill(ind)) |
|
|
|
|
temp.V(ind) = temp.Fillval(); |
|
|
|
|
else |
|
|
|
|
temp.V(ind) = PTemp2Temp(temp.V(ind), sal.V(ind), Depth(p->layer), temp.Lon(ind), temp.Lat(ind)); |
|
|
|
|
temp.V(ind) = PTemp2Temp(ptemp.V(ind), sal.V(ind), Depth(p->layer), temp.Lon(ind), temp.Lat(ind)); |
|
|
|
|
} |
|
|
|
|
return temp; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
// pdens from temp and sal
|
|
|
|
|
if(vname == "pdens") |
|
|
|
|
{ |
|
|
|
|
bool tempispot = HaveVar("ptemp"); |
|
|
|
|
auto temp = Read(tempispot ? "ptemp" : "temp", ip, i); |
|
|
|
|
auto sal = Read("sal", ip, i); |
|
|
|
|
if(!(temp && sal)) return Data(); |
|
|
|
|
temp.SetUnit("kg m-3"); |
|
|
|
|
for(size_t ind = 0; ind < temp.N(); ind++) |
|
|
|
|
if(!(Read(tempispot ? "ptemp" : "temp", cache, ip, i) && Read("sal", cache, ip, i))) return false; |
|
|
|
|
cache[vname] = cache.at("sal").CopyGrid(); |
|
|
|
|
auto& pdens = cache.at(vname); |
|
|
|
|
const auto& temp = cache.at(tempispot ? "ptemp" : "temp"); |
|
|
|
|
const auto& sal = cache.at("sal"); |
|
|
|
|
pdens.SetUnit("kg m-3"); |
|
|
|
|
for(size_t ind = 0; ind < pdens.N(); ind++) |
|
|
|
|
{ |
|
|
|
|
if(temp.IsFill(ind) || sal.IsFill(ind)) |
|
|
|
|
temp.V(ind) = temp.Fillval(); |
|
|
|
|
pdens.V(ind) = pdens.Fillval(); |
|
|
|
|
else |
|
|
|
|
temp.V(ind) = tempispot ? PTemp2PDens(temp.V(ind), sal.V(ind), Depth(p->layer), temp.Lon(ind), temp.Lat(ind)) |
|
|
|
|
: Temp2PDens(temp.V(ind), sal.V(ind), Depth(p->layer), temp.Lon(ind), temp.Lat(ind)); |
|
|
|
|
pdens.V(ind) = tempispot ? PTemp2PDens(temp.V(ind), sal.V(ind), Depth(p->layer), pdens.Lon(ind), pdens.Lat(ind)) |
|
|
|
|
: Temp2PDens(temp.V(ind), sal.V(ind), Depth(p->layer), pdens.Lon(ind), pdens.Lat(ind)); |
|
|
|
|
} |
|
|
|
|
return temp; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
// U and U2 from u and v
|
|
|
|
|
if(vname == "U" || vname == "U2") |
|
|
|
|
{ |
|
|
|
|
bool square = vname == "U2"; |
|
|
|
|
auto u = Read("u", ip, i); |
|
|
|
|
auto v = Read("v", ip, i); |
|
|
|
|
if(!(u && v)) return Data(); |
|
|
|
|
if(square && u.Unit().Exist()) u.SetUnit("(" + u.Unit() + ")2"); |
|
|
|
|
for(size_t ind = 0; ind < u.N(); ind++) |
|
|
|
|
if(!(Read("u", cache, ip, i) && Read("v", cache, ip, i))) return false; |
|
|
|
|
cache[vname] = cache.at("u").CopyGrid(); |
|
|
|
|
auto& U = cache.at(vname); |
|
|
|
|
const auto& u = cache.at("u"); |
|
|
|
|
const auto& v = cache.at("v"); |
|
|
|
|
if(u.Unit().Exist()) U.SetUnit(square ? ("(" + u.Unit() + ")2") : u.Unit()); |
|
|
|
|
for(size_t ind = 0; ind < U.N(); ind++) |
|
|
|
|
{ |
|
|
|
|
if(u.IsFill(ind) || v.IsFill(ind)) |
|
|
|
|
u.V(ind) = u.Fillval(); |
|
|
|
|
U.V(ind) = U.Fillval(); |
|
|
|
|
else |
|
|
|
|
u.V(ind) = square ? (u(ind) * u(ind) + v(ind) * v(ind)) : michlib::Hypot(u(ind), v(ind)); |
|
|
|
|
U.V(ind) = square ? (u(ind) * u(ind) + v(ind) * v(ind)) : michlib::Hypot(u(ind), v(ind)); |
|
|
|
|
} |
|
|
|
|
return u; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return Data(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Direct read
|
|
|
|
|
bool nodepth = false; |
|
|
|
|
Data data; |
|
|
|
|
auto head = nc[id]->Header(); |
|
|
|
|
for(const auto& v: head.Variables()) |
|
|
|
|
if(v.Name() == name) |
|
|
|
|
{ |
|
|
|
|
if(v.Dimensions().size() == 3) nodepth = true; |
|
|
|
|
if(v.Type().Id() == NC_SHORT) return ReadVarRaw<int2>(nc[id], name, tid, nodepth, p); |
|
|
|
|
if(v.Type().Id() == NC_INT) return ReadVarRaw<int>(nc[id], name, tid, nodepth, p); |
|
|
|
|
if(v.Type().Id() == NC_FLOAT) return ReadVarRaw<float>(nc[id], name, tid, nodepth, p); |
|
|
|
|
if(v.Type().Id() == NC_DOUBLE) return ReadVarRaw<double>(nc[id], name, tid, nodepth, p); |
|
|
|
|
if(v.Type().Id() == NC_SHORT) data = ReadVarRaw<int2>(nc[id], name, tid, nodepth, p); |
|
|
|
|
if(v.Type().Id() == NC_INT) data = ReadVarRaw<int>(nc[id], name, tid, nodepth, p); |
|
|
|
|
if(v.Type().Id() == NC_FLOAT) data = ReadVarRaw<float>(nc[id], name, tid, nodepth, p); |
|
|
|
|
if(v.Type().Id() == NC_DOUBLE) data = ReadVarRaw<double>(nc[id], name, tid, nodepth, p); |
|
|
|
|
if(data) |
|
|
|
|
{ |
|
|
|
|
cache[vname] = std::move(data); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return Data(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<class DataType> LayeredData::Data LayeredData::ReadVarRaw(const NC& f, const MString& name, size_t i, bool nodepth, const struct LayeredData::Parameters* p) const |
|
|
|
|