Observation operators
Description and details of CARDAMOM observation operators
To write a new observation operator for a time series observation:
choose cbf quantity name and model quantity name (e.g.,
GPP
andM_GPP
), and type (TIMESERIES_OBS_STRUCT
,SINGLE_OBS_STRUCT
,TIMESERIES_DRIVER_STRUCT
)in
CARDAMOM_DATA_STRUCTURE.c
, model quantity name (e.g.,M_GPP
) is instantiatedin
CARDAMOM_NETCDF_DATA_STRUCTURE.c
, cbf quantity name (e.g.,GPP
) is instantiated as a specific type (e.g.,TIMESERIES_OBS_STRUCT GPP
)in
CARDAMOM_READ NETCDF_DATA.c
cbf quantity name (e.g.,
"GPP"
) gets included, with the corresponding function for its type (e.g.,DATA->GPP=READ_NETCDF_TIMESERIES_OBS_FIELDS(ncid, "GPP");
for time series type obs, or other for single obs or driver types);If timeseries obs, also call the preprocess function (e.g.,
TIMESERIES_OBS_STRUCT_PREPROCESS(&DATA->GPP);
)
in
DALEC_OBSERVATION_OPERATORS.c
,create boolean flag to support the obsop, (e.g.:
bool SUPPORT_GPP_OBS;
)instantiate any sub quantities that might be needed to evaluate the observation operator (e.g.,
int Rauto_flux; int GPP_flux;
where bothGPP_flux
andRauto_flux
are quantities used in the CUE observation operator)set the boolean flag to false by default in the obsop data structure (e.g.,
OBSOPE->SUPPORT_GPP_OBS=false;
) This gets changed inDALEC_1100.c
on a case by case basis.Add to DALEC obsope structure (e.g.,
if (O->SUPPORT_GPP_OBS){DALEC_OBSOPE_GPP(D, O);}
)write the observation operator evaluation as a function of the data structure and the obsop structure, e.g.:
int DALEC_OBSOPE_GPP(DATA * D, OBSOPE * O){ //GPP timeseries length int N=D->ncdf_data.TIME_INDEX.length; //Time varying GPP TIMESERIES_OBS_STRUCT TOBS=D->ncdf_data.GPP; if (TOBS.validobs){int n; for (n=0;n<N;n++){ D->M_GPP[n]=D->M_FLUXES[D->nofluxes*n+O->GPP_flux]; } }; //Mean GPP SINGLE_OBS_STRUCT SOBS=D->ncdf_data.Mean_GPP; if (SOBS.validobs){ int n; D->M_Mean_GPP=0; for (n=0;n<N;n++){ D->M_Mean_GPP+=D->M_FLUXES[n*D->nofluxes+O->GPP_flux]; }; D->M_Mean_GPP=D->M_Mean_GPP/(double)N; } return 0; }
in
DALEC_ALL_LIKELIHOOD.c
,add to the list of likelihood indices (e.g.,
int GPP;
)increment likelihood index count (e.g.,
…20,21,22};
)add to the likelihood function (e.g.,
if (O->SUPPORT_GPP_OBS){ML[LI.GPP]=CARDAMOM_TIMESERIES_OBS_LIKELIHOOD(&D.ncdf_data.GPP, D.M_GPP);};
)
in
DALEC_1100.c
,create and assign the model quantities that are needed to evaluate the obsop, matching variable names declared in step b of modifying
DALEC_OBSERVATION_OPERATORS.c
(e.g.,OBSOPE.GPP_flux=F.gpp;
) andturn the obsop on (e.g.,
OBSOPE.SUPPORT_GPP_OBS=true;
)
If this is a completely new variable for the CBF, then in
CARDAMOM_READ_BINARY_DATA.c
, add a memory allocation (e.g.,DATA->M_GPP=calloc(Ntimesteps,sizeof(double));
) NOTE: can trigger bus error if skippedWhen putting data into the CBF under the new field, also check