1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
/***********************************************/
/**
* @file normalsTemporalCombination.cpp
*
* @brief Normal equations of trend, annual from a time series of normal equations.
*
* @author Torsten Mayer-Guerr
* @date 2016-03-03
*/
/***********************************************/
// Latex documentation
#define DOCSTRING docstring
static const char *docstring = R"(
This program reads a times series of \configFile{inputfileNormalequation}{normalEquation}
with asscociated \configClass{timeSeries}{timeSeriesType} and setup a new combined normal equation system.
For each parameter a \configClass{parametrizationTemporal}{parametrizationTemporalType} is used.
It can be used to estimate trend and annual spherical harmonic coefficients from monthly GRACE normal equations.
)";
/***********************************************/
#include "programs/program.h"
#include "parallel/matrixDistributed.h"
#include "files/fileNormalEquation.h"
#include "classes/timeSeries/timeSeries.h"
#include "classes/parametrizationTemporal/parametrizationTemporal.h"
/***** CLASS ***********************************/
/** @brief Normal equations of trend, annual from a time series of normal equations.
* @ingroup programsGroup */
class NormalsTemporalCombination
{
public:
void run(Config &config, Parallel::CommunicatorPtr comm);
};
GROOPS_REGISTER_PROGRAM(NormalsTemporalCombination, PARALLEL, "normal equations of trend, annual from a time series of normal equations", NormalEquation)
/***********************************************/
void NormalsTemporalCombination::run(Config &config, Parallel::CommunicatorPtr comm)
{
try
{
FileName fileNameOut;
std::vector<FileName> fileNameIn;
ParametrizationTemporalPtr temporal;
TimeSeriesPtr timeSeries;
renameDeprecatedConfig(config, "outputfileNormalequation", "outputfileNormalEquation", date2time(2020, 6, 3));
renameDeprecatedConfig(config, "inputfileNormalequation", "inputfileNormalEquation", date2time(2020, 6, 3));
renameDeprecatedConfig(config, "temporalRepresentation", "parametrizationTemporal", date2time(2020, 6, 3));
readConfig(config, "outputfileNormalEquation", fileNameOut, Config::MUSTSET, "", "");
readConfig(config, "inputfileNormalEquation", fileNameIn, Config::MUSTSET, "", "normal equations for each point in time");
readConfig(config, "timeSeries", timeSeries, Config::MUSTSET, "", "times of each normal equations");
readConfig(config, "parametrizationTemporal", temporal, Config::MUSTSET, "", "");
if(isCreateSchema(config)) return;
// =============================================
// Create time series
// ------------------
std::vector<Time> times = timeSeries->times();
if(times.size() != fileNameIn.size())
throw(Exception("fileCount("+fileNameIn.size()%"%i) != timeCount("s+times.size()%"%i)-1"s));
// =============================================
// read normal equations
// ---------------------
logStatus<<"read normal equations"<<Log::endl;
MatrixDistributed normal;
Matrix nTotal;
NormalEquationInfo infoTotal;
Single::forEach(times.size(), [&](UInt idEpoch)
{
// read normals
// ------------
Matrix N, n;
NormalEquationInfo info;
try
{
readFileNormalEquation(fileNameIn.at(idEpoch), info, N, n);
}
catch(std::exception &e)
{
logWarningOnce<<e.what()<<" continue..."<<Log::endl;
return;
}
// init normals
// ------------
const Vector factorTemporal = temporal->factors(times.at(idEpoch));
if(normal.parameterCount()==0)
{
std::vector<UInt> blockIndex(factorTemporal.size()+1);
for(UInt i=0; i<=factorTemporal.rows(); i++)
blockIndex.at(i) = i*N.rows();
normal.initEmpty(blockIndex, comm);
nTotal = Matrix(normal.parameterCount(), n.columns());
infoTotal.lPl = Vector(n.columns());
}
// test dimension
// --------------
if((n.rows() != normal.blockSize(0)) || (n.columns() != nTotal.columns()))
throw(Exception("Normal equation dimension mismatch"));
// parameter names
// ---------------
if(!infoTotal.parameterName.size())
infoTotal.parameterName = info.parameterName;
else
for(UInt i=0; i<infoTotal.parameterName.size(); i++)
if(!infoTotal.parameterName.at(i).combine(info.parameterName.at(i)))
logWarning<<"Parameter names do not match at index "<<i<<": '"<<infoTotal.parameterName.at(i).str()<<"' != '"<< info.parameterName.at(i).str()<<"'"<< Log::endl;
// setup normal matrix
// -------------------
fillSymmetric(N);
for(UInt i=0; i<normal.blockCount(); i++)
for(UInt k=i; k<normal.blockCount(); k++)
if(factorTemporal(i) != 0 && factorTemporal(k) != 0)
{
normal.setBlock(i, k);
if(normal.isMyRank(i,k))
axpy(factorTemporal(i)*factorTemporal(k), N, normal.N(i,k));
}
if(Parallel::isMaster(comm))
{
for(UInt i=0; i<normal.blockCount(); i++)
axpy(factorTemporal(i), n, nTotal.row(normal.blockIndex(i), normal.blockSize(i)));
infoTotal.observationCount += info.observationCount;
infoTotal.lPl += info.lPl;
}
});
// =============================================
// adjust parameter names based on temporal representation
// -------------------------------------------------------
std::vector<ParameterName> baseName;
std::swap(infoTotal.parameterName, baseName);
temporal->parameterName(baseName, infoTotal.parameterName);
// write normal equations
// ----------------------
logStatus<<"write normal equations to <"<<fileNameOut<<">"<<Log::endl;
writeFileNormalEquation(fileNameOut, infoTotal, normal, nTotal);
}
catch(std::exception &e)
{
GROOPS_RETHROW(e)
}
}
/***********************************************/
|