|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
#define MICHLIB_NOSOURCE |
|
|
|
|
#include "CF.h" |
|
|
|
|
#include "gsw.h" |
|
|
|
|
|
|
|
|
|
using michlib::DetGeoDomain; |
|
|
|
|
|
|
|
|
@ -447,15 +448,257 @@ Error CF::FillAdapterFromCF(const CLArgs& args, michlib_internal::ParameterListE
|
|
|
|
|
return Error(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
RetVal<std::shared_ptr<Data2D>> CF::PTemp3DReader(const Adapter& ad, const void* vinfo, std::shared_ptr<Projection> proj, std::shared_ptr<Vertical> vert, size_t it) |
|
|
|
|
RetVal<std::shared_ptr<Data3D>> CF::TEOS103DReader(Adapter& ad, const Adapter::VInfoBase* vinfo, std::shared_ptr<Projection> proj, std::shared_ptr<Vertical> vert, size_t it) |
|
|
|
|
{ |
|
|
|
|
static const MString pref = "CF::PTemp3DReader"; |
|
|
|
|
static const MString pref = "CF::TempSalDer3DReader"; |
|
|
|
|
|
|
|
|
|
auto v = michlib::pointer_cast<const struct Adapter::VInfo*>(vinfo); |
|
|
|
|
|
|
|
|
|
const struct Adapter::ReadInfo* ri = v->rinfo.get(); |
|
|
|
|
const auto* v = dynamic_cast<const struct VInfoTEOS10*>(vinfo); |
|
|
|
|
if(v == nullptr) return {pref, "Incorrect argument type"}; |
|
|
|
|
|
|
|
|
|
std::shared_ptr<Data3D> out(new Data3D(proj, vert, {.unit = v->targetunit, .stname = v->stname, .lname = v->lname, .comment = v->comment})); |
|
|
|
|
|
|
|
|
|
std::shared_ptr<Data3D> temp, sal; |
|
|
|
|
{ |
|
|
|
|
auto rettemp = ad.Read3D(v->tempvar, ad.CurrentTime()); |
|
|
|
|
if(!rettemp) return {pref, "Can't read temperature variable " + v->tempvar}; |
|
|
|
|
temp = rettemp.Value(); |
|
|
|
|
} |
|
|
|
|
{ |
|
|
|
|
auto retsal = ad.Read3D(v->salvar, ad.CurrentTime()); |
|
|
|
|
if(!retsal) return {pref, "Can't read salinity variable " + v->salvar}; |
|
|
|
|
sal = retsal.Value(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(temp->Nz() != sal->Nz()) return {pref, MString("For temperature variable Nz=") + temp->Nz() + ", for salinity variable Nz=" + sal->Nz()}; |
|
|
|
|
if(temp->Ny() != sal->Ny()) return {pref, MString("For temperature variable Ny=") + temp->Ny() + ", for salinity variable Ny=" + sal->Ny()}; |
|
|
|
|
if(temp->Nx() != sal->Nx()) return {pref, MString("For temperature variable Nx=") + temp->Nx() + ", for salinity variable Nx=" + sal->Nx()}; |
|
|
|
|
|
|
|
|
|
if(temp->Nz() != out->Nz()) return {pref, MString("For temperature variable Nz=") + temp->Nz() + ", for output variable Nz=" + out->Nz()}; |
|
|
|
|
if(temp->Ny() != out->Ny()) return {pref, MString("For temperature variable Ny=") + temp->Ny() + ", for output variable Ny=" + out->Ny()}; |
|
|
|
|
if(temp->Nx() != out->Nx()) return {pref, MString("For temperature variable Nx=") + temp->Nx() + ", for output variable Nx=" + out->Nx()}; |
|
|
|
|
|
|
|
|
|
switch(v->op) |
|
|
|
|
{ |
|
|
|
|
case(VInfoTEOS10::TEMP2PTEMP): |
|
|
|
|
{ |
|
|
|
|
for(size_t iz = 0; iz < out->Nz(); iz++) |
|
|
|
|
for(size_t iy = 0; iy < out->Ny(); iy++) |
|
|
|
|
for(size_t ix = 0; ix < out->Nx(); ix++) |
|
|
|
|
(*out)(ix, iy, iz) = (temp->IsFill(ix, iy, iz) || sal->IsFill(ix, iy, iz)) |
|
|
|
|
? out->Fillval() |
|
|
|
|
: Temp2PTemp((*temp)(ix, iy, iz), (*sal)(ix, iy, iz), out->Depth(ix, iy, iz), out->Lon(ix, iy), out->Lat(ix, iy)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case(VInfoTEOS10::PTEMP2TEMP): |
|
|
|
|
{ |
|
|
|
|
for(size_t iz = 0; iz < out->Nz(); iz++) |
|
|
|
|
for(size_t iy = 0; iy < out->Ny(); iy++) |
|
|
|
|
for(size_t ix = 0; ix < out->Nx(); ix++) |
|
|
|
|
(*out)(ix, iy, iz) = (temp->IsFill(ix, iy, iz) || sal->IsFill(ix, iy, iz)) |
|
|
|
|
? out->Fillval() |
|
|
|
|
: PTemp2Temp((*temp)(ix, iy, iz), (*sal)(ix, iy, iz), out->Depth(ix, iy, iz), out->Lon(ix, iy), out->Lat(ix, iy)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case(VInfoTEOS10::TEMP2PDENS): |
|
|
|
|
{ |
|
|
|
|
for(size_t iz = 0; iz < out->Nz(); iz++) |
|
|
|
|
for(size_t iy = 0; iy < out->Ny(); iy++) |
|
|
|
|
for(size_t ix = 0; ix < out->Nx(); ix++) |
|
|
|
|
(*out)(ix, iy, iz) = (temp->IsFill(ix, iy, iz) || sal->IsFill(ix, iy, iz)) |
|
|
|
|
? out->Fillval() |
|
|
|
|
: Temp2PDens((*temp)(ix, iy, iz), (*sal)(ix, iy, iz), out->Depth(ix, iy, iz), out->Lon(ix, iy), out->Lat(ix, iy)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case(VInfoTEOS10::PTEMP2PDENS): |
|
|
|
|
{ |
|
|
|
|
for(size_t iz = 0; iz < out->Nz(); iz++) |
|
|
|
|
for(size_t iy = 0; iy < out->Ny(); iy++) |
|
|
|
|
for(size_t ix = 0; ix < out->Nx(); ix++) |
|
|
|
|
(*out)(ix, iy, iz) = (temp->IsFill(ix, iy, iz) || sal->IsFill(ix, iy, iz)) |
|
|
|
|
? out->Fillval() |
|
|
|
|
: PTemp2PDens((*temp)(ix, iy, iz), (*sal)(ix, iy, iz), out->Depth(ix, iy, iz), out->Lon(ix, iy), out->Lat(ix, iy)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case(VInfoTEOS10::TEMP2SSPEED): |
|
|
|
|
{ |
|
|
|
|
for(size_t iz = 0; iz < out->Nz(); iz++) |
|
|
|
|
for(size_t iy = 0; iy < out->Ny(); iy++) |
|
|
|
|
for(size_t ix = 0; ix < out->Nx(); ix++) |
|
|
|
|
(*out)(ix, iy, iz) = (temp->IsFill(ix, iy, iz) || sal->IsFill(ix, iy, iz)) |
|
|
|
|
? out->Fillval() |
|
|
|
|
: Temp2SSpeed((*temp)(ix, iy, iz), (*sal)(ix, iy, iz), out->Depth(ix, iy, iz), out->Lon(ix, iy), out->Lat(ix, iy)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case(VInfoTEOS10::PTEMP2SSPEED): |
|
|
|
|
{ |
|
|
|
|
for(size_t iz = 0; iz < out->Nz(); iz++) |
|
|
|
|
for(size_t iy = 0; iy < out->Ny(); iy++) |
|
|
|
|
for(size_t ix = 0; ix < out->Nx(); ix++) |
|
|
|
|
(*out)(ix, iy, iz) = (temp->IsFill(ix, iy, iz) || sal->IsFill(ix, iy, iz)) |
|
|
|
|
? out->Fillval() |
|
|
|
|
: PTemp2SSpeed((*temp)(ix, iy, iz), (*sal)(ix, iy, iz), out->Depth(ix, iy, iz), out->Lon(ix, iy), out->Lat(ix, iy)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Error CF::TEOS10Module(const CLArgs& args, michlib_internal::ParameterListEx& pars, Adapter& ad) |
|
|
|
|
{ |
|
|
|
|
static const MString pref = "TempSalDerModule"; |
|
|
|
|
|
|
|
|
|
MString sal, temp, ptemp; |
|
|
|
|
|
|
|
|
|
for(const auto& v: ad.Vars()) |
|
|
|
|
{ |
|
|
|
|
if(!ad.Is3D(v.first)) continue; |
|
|
|
|
const auto& info = v.second.info; |
|
|
|
|
|
|
|
|
|
if(!sal.Exist() && info->stname == "sea_water_salinity") sal = v.first; |
|
|
|
|
if(!temp.Exist() && info->stname == "sea_water_temperature") temp = v.first; |
|
|
|
|
if(!ptemp.Exist() && info->stname == "sea_water_potential_temperature") ptemp = v.first; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// From potential temperature and salinity
|
|
|
|
|
if(sal.Exist() && ptemp.Exist()) |
|
|
|
|
{ |
|
|
|
|
const auto& tvar = ad.Vars().at(ptemp); |
|
|
|
|
const auto& svar = ad.Vars().at(sal); |
|
|
|
|
const auto& tproj = tvar.proj; |
|
|
|
|
const auto& sproj = svar.proj; |
|
|
|
|
const auto& tvert = tvar.vert; |
|
|
|
|
const auto& svert = svar.vert; |
|
|
|
|
const auto& tfill = tvar.info->fillval; |
|
|
|
|
const auto& rinfo = tvar.info->rinfo; |
|
|
|
|
|
|
|
|
|
if(sproj != tproj) return Error(pref, "Salinity variable " + sal + " and potential temperature variable " + ptemp + " have different horizontal grids"); |
|
|
|
|
if(svert != tvert) return Error(pref, "Salinity variable " + sal + " and potential temperature variable " + ptemp + " have different vertical grids"); |
|
|
|
|
|
|
|
|
|
{ // Temperature
|
|
|
|
|
auto vinfo = new VInfoTEOS10(); |
|
|
|
|
|
|
|
|
|
vinfo->tempvar = ptemp; |
|
|
|
|
vinfo->salvar = sal; |
|
|
|
|
vinfo->op = VInfoTEOS10::PTEMP2TEMP; |
|
|
|
|
|
|
|
|
|
vinfo->stname = "sea_water_temperature"; |
|
|
|
|
vinfo->lname = "Temperature"; |
|
|
|
|
vinfo->comment = "Module TEOS-10: Temperature calculated from potential temperature (" + ptemp + ") and salinity (" + sal + ")"; |
|
|
|
|
vinfo->targetunit = "degrees_C"; |
|
|
|
|
vinfo->rinfo = rinfo; |
|
|
|
|
vinfo->fillval = tfill; |
|
|
|
|
|
|
|
|
|
const bool addsuc = ad.Add3DVariable("temp", Adapter::VInfo(vinfo), tproj, tvert, TEOS103DReader); |
|
|
|
|
if(!addsuc) return {pref, "Variable with name temp already exist"}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Potential density
|
|
|
|
|
auto vinfo = new VInfoTEOS10(); |
|
|
|
|
|
|
|
|
|
vinfo->tempvar = ptemp; |
|
|
|
|
vinfo->salvar = sal; |
|
|
|
|
vinfo->op = VInfoTEOS10::PTEMP2PDENS; |
|
|
|
|
|
|
|
|
|
vinfo->stname = "sea_water_sigma_theta"; |
|
|
|
|
vinfo->lname = "Potential density minus 1000 kg m-3"; |
|
|
|
|
vinfo->comment = "Module TEOS-10: Potential density calculated from potential temperature (" + ptemp + ") and salinity (" + sal + ")"; |
|
|
|
|
vinfo->targetunit = "kg m-3"; |
|
|
|
|
vinfo->rinfo = rinfo; |
|
|
|
|
vinfo->fillval = NAN; |
|
|
|
|
|
|
|
|
|
const bool addsuc = ad.Add3DVariable("pdens", Adapter::VInfo(vinfo), tproj, tvert, TEOS103DReader); |
|
|
|
|
if(!addsuc) return {pref, "Variable with name pdens already exist"}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Sound speed
|
|
|
|
|
auto vinfo = new VInfoTEOS10(); |
|
|
|
|
|
|
|
|
|
vinfo->tempvar = ptemp; |
|
|
|
|
vinfo->salvar = sal; |
|
|
|
|
vinfo->op = VInfoTEOS10::PTEMP2SSPEED; |
|
|
|
|
|
|
|
|
|
vinfo->stname = "speed_of_sound_in_sea_water"; |
|
|
|
|
vinfo->lname = "Sound speed"; |
|
|
|
|
vinfo->comment = "Module TEOS-10: Sound speed calculated from potential temperature (" + ptemp + ") and salinity (" + sal + ")"; |
|
|
|
|
vinfo->targetunit = "m s-1"; |
|
|
|
|
vinfo->rinfo = rinfo; |
|
|
|
|
vinfo->fillval = NAN; |
|
|
|
|
|
|
|
|
|
const bool addsuc = ad.Add3DVariable("sspeed", Adapter::VInfo(vinfo), tproj, tvert, TEOS103DReader); |
|
|
|
|
if(!addsuc) return {pref, "Variable with name sspeed already exist"}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// From temperature and salinity
|
|
|
|
|
if(sal.Exist() && temp.Exist()) |
|
|
|
|
{ |
|
|
|
|
const auto& tvar = ad.Vars().at(temp); |
|
|
|
|
const auto& svar = ad.Vars().at(sal); |
|
|
|
|
const auto& tproj = tvar.proj; |
|
|
|
|
const auto& sproj = svar.proj; |
|
|
|
|
const auto& tvert = tvar.vert; |
|
|
|
|
const auto& svert = svar.vert; |
|
|
|
|
const auto& tfill = tvar.info->fillval; |
|
|
|
|
const auto& rinfo = tvar.info->rinfo; |
|
|
|
|
|
|
|
|
|
if(sproj != tproj) return Error(pref, "Salinity variable " + sal + " and temperature variable " + temp + " have different horizontal grids"); |
|
|
|
|
if(svert != tvert) return Error(pref, "Salinity variable " + sal + " and temperature variable " + temp + " have different vertical grids"); |
|
|
|
|
|
|
|
|
|
{ // Potential temperature
|
|
|
|
|
auto vinfo = new VInfoTEOS10(); |
|
|
|
|
|
|
|
|
|
vinfo->tempvar = temp; |
|
|
|
|
vinfo->salvar = sal; |
|
|
|
|
vinfo->op = VInfoTEOS10::TEMP2PTEMP; |
|
|
|
|
|
|
|
|
|
vinfo->stname = "sea_water_potential_temperature"; |
|
|
|
|
vinfo->lname = "Potential temperature"; |
|
|
|
|
vinfo->comment = "Module TEOS-10: Potential temperature calculated from temperature (" + temp + ") and salinity (" + sal + ")"; |
|
|
|
|
vinfo->targetunit = "degrees_C"; |
|
|
|
|
vinfo->rinfo = rinfo; |
|
|
|
|
vinfo->fillval = tfill; |
|
|
|
|
|
|
|
|
|
const bool addsuc = ad.Add3DVariable("ptemp", Adapter::VInfo(vinfo), tproj, tvert, TEOS103DReader); |
|
|
|
|
if(!addsuc) return {pref, "Variable with name ptemp already exist"}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Potential density
|
|
|
|
|
auto vinfo = new VInfoTEOS10(); |
|
|
|
|
|
|
|
|
|
vinfo->tempvar = temp; |
|
|
|
|
vinfo->salvar = sal; |
|
|
|
|
vinfo->op = VInfoTEOS10::TEMP2PDENS; |
|
|
|
|
|
|
|
|
|
vinfo->stname = "sea_water_sigma_theta"; |
|
|
|
|
vinfo->lname = "Potential density minus 1000 kg m-3"; |
|
|
|
|
vinfo->comment = "Module TEOS-10: Potential density calculated from temperature (" + temp + ") and salinity (" + sal + ")"; |
|
|
|
|
vinfo->targetunit = "kg m-3"; |
|
|
|
|
vinfo->rinfo = rinfo; |
|
|
|
|
vinfo->fillval = NAN; |
|
|
|
|
|
|
|
|
|
const bool addsuc = ad.Add3DVariable("pdens", Adapter::VInfo(vinfo), tproj, tvert, TEOS103DReader); |
|
|
|
|
if(!addsuc) return {pref, "Variable with name pdens already exist"}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ // Sound speed
|
|
|
|
|
auto vinfo = new VInfoTEOS10(); |
|
|
|
|
|
|
|
|
|
vinfo->tempvar = temp; |
|
|
|
|
vinfo->salvar = sal; |
|
|
|
|
vinfo->op = VInfoTEOS10::TEMP2SSPEED; |
|
|
|
|
|
|
|
|
|
vinfo->stname = "speed_of_sound_in_sea_water"; |
|
|
|
|
vinfo->lname = "Sound speed"; |
|
|
|
|
vinfo->comment = "Module TEOS-10: Sound speed calculated from temperature (" + temp + ") and salinity (" + sal + ")"; |
|
|
|
|
vinfo->targetunit = "m s-1"; |
|
|
|
|
vinfo->rinfo = rinfo; |
|
|
|
|
vinfo->fillval = NAN; |
|
|
|
|
|
|
|
|
|
const bool addsuc = ad.Add3DVariable("sspeed", Adapter::VInfo(vinfo), tproj, tvert, TEOS103DReader); |
|
|
|
|
if(!addsuc) return {pref, "Variable with name sspeed already exist"}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|