Canoe
Comprehensive Atmosphere N' Ocean Engine
inversion.cpp
Go to the documentation of this file.
1 // C/C++ headers
2 #include <iostream>
3 #include <stdexcept>
4 #include <string>
5 #include <utility>
6 
7 // athena
8 #include <athena/coordinates/coordinates.hpp>
9 #include <athena/mesh/mesh.hpp>
10 #include <athena/parameter_input.hpp>
11 
12 // application
13 #include <application/application.hpp>
14 #include <application/exceptions.hpp>
15 
16 // utils
17 #include <utils/fileio.hpp>
18 #include <utils/ndarrays.hpp>
19 #include <utils/vectorize.hpp>
20 
21 // inversion
22 #include "inversion.hpp"
23 #include "profile_inversion.hpp"
24 
25 Inversion::Inversion(MeshBlock *pmb, ParameterInput *pin, std::string name)
26  : NamedGroup(name),
27  mcmc_initialized_(false),
28  init_pos_(nullptr),
29  pmy_block_(pmb) {
30  Application::Logger app("inversion");
31  app->Log("Initialize Inversion");
32 
33  opts_.a = pin->GetOrAddReal("inversion", "stretch", 2.);
34  opts_.p = pin->GetOrAddInteger("inversion", "walk", 4);
35  opts_.print = pin->GetOrAddInteger("inversion", "print", 100);
36 
37 #ifdef MPI_PARALLEL
38  opts_.mpi_comm = MPI_COMM_WORLD;
39 #endif
40 
41  snprintf(opts_.logfile, sizeof(opts_.logfile), "%s",
42  pin->GetOrAddString("inversion", name + ".logfile",
43  name + "_inversion.log")
44  .c_str());
45 
46  std::string obsfile = pin->GetOrAddString("inversion", "obsfile", "none");
47  if (obsfile != "none") {
49  // app->Log("target = ", target_.transpose());
50  // app->Log("inverse covariance matrx = ", icov_);
51  } else {
52  target_.resize(1);
53  icov_.resize(1, 1);
54  }
55 
56  // fit differential
57  fit_differential_ = pin->GetOrAddBoolean("inversion", "differential", false);
58  // app->Log("fit differential = ", fit_differential_);
59 }
60 
62  if (mcmc_initialized_) {
63  mcmc_free(&recs_);
64  delete[] zz_;
65  delete[] par_;
66  }
67 
68  if (init_pos_ != nullptr) FreeCArray(init_pos_);
69 }
70 
71 void Inversion::InitializeChain(int nstep, int nwalker, int ndim, int nvalue) {
72  // mcmc_alloc(&recs_, pmy_block->pmy_mesh->nlim+1, nwalker, ndim, nvalue);
73  mcmc_alloc(&recs_, nstep, nwalker, ndim, nvalue);
74  mcmc_initialized_ = true;
75  zz_ = new Real[nwalker];
76  par_ = new Real[ndim];
77 }
78 
79 void Inversion::MakeMCMCOutputs(std::string fname) {
80  Application::Logger app("inversion");
81  app->Log("Make MCMC Outputs");
82 
83  if (!mcmc_initialized_) {
84  app->Error("mcmc chain uninitialized");
85  }
86  mcmc_save_fits(fname.c_str(), &opts_, &recs_);
87 }
88 
90  Application::Logger app("inversion");
91  app->Log("Reset MCMC Chain");
92 
93  if (!mcmc_initialized_) {
94  app->Error("mcmc chain uninitialized");
95  }
96 
97  int cur = recs_.cur;
98  if (cur == 0) return;
99 
100  // copy the last state into the first state
101  for (int k = 0; k < recs_.nwalker; ++k) {
102  for (int d = 0; d < recs_.ndim; ++d)
103  recs_.par[0][k][d] = recs_.par[cur - 1][k][d];
104  for (int d = 0; d < recs_.nvalue; ++d)
105  recs_.val[0][k][d] = recs_.val[cur - 1][k][d];
106  recs_.lnp[0][k] = recs_.lnp[cur - 1][k];
107  recs_.newstate[0][k] = recs_.newstate[cur - 1][k];
108  }
109 
110  recs_.reset += cur - 1;
111  recs_.cur = 1;
112 
113  int nstep = recs_.nstep - 1;
114  int nwalker = recs_.nwalker;
115  int ndim = recs_.ndim;
116  int nvalue = recs_.nvalue;
117 
118  memset(recs_.par[1][0], 0, nstep * nwalker * ndim * sizeof(double));
119  memset(recs_.val[1][0], 0, nstep * nwalker * nvalue * sizeof(double));
120  memset(recs_.lnp[1], 0, nstep * nwalker * sizeof(double));
121  memset(recs_.newstate[1], 0, nstep * nwalker * sizeof(int));
122 }
123 
124 AllInversions InversionsFactory::Create(MeshBlock *pmb, ParameterInput *pin) {
125  Application::Logger app("inversion");
126  app->Log("Create inversion queue");
127 
128  std::string str = pin->GetOrAddString("inversion", "tasks", "");
129  std::vector<std::string> task_names =
130  Vectorize<std::string>(str.c_str(), " ,");
131 
132  AllInversions all_fits;
133  InversionPtr pfit;
134 
135  for (auto p : task_names) {
136  if (p == "VLAProfileInversion") {
137  pfit = std::make_shared<VLAProfileInversion>(pmb, pin);
138  } else if (p == "JunoProfileInversion") {
139  pfit = std::make_shared<JunoProfileInversion>(pmb, pin);
140  } else if (p == "VLACompositionInversion") {
141  } else if (p == "JunoCompositionInversion") {
142  } else {
143  throw NotFoundError("CreateAllInversions", p);
144  }
145  all_fits.push_back(std::move(pfit));
146  }
147 
148  int jl = pmb->js;
149  for (auto &q : all_fits) {
150  q->InitializePositions();
151  q->setX2Indices(jl);
152  jl += q->getX2Span();
153  }
154 
155  app->Log("Number of inversions = " + std::to_string(all_fits.size()));
156 
157  return all_fits;
158 }
159 
160 namespace InversionHelper {
161 #define MAX_LINE 512
162 void read_observation_file(Eigen::VectorXd *target, Eigen::MatrixXd *icov,
163  std::string fname) {
164  std::stringstream msg;
165  FILE *fp = fopen(fname.c_str(), "r");
166  if (fp == NULL) {
167  msg << "### FATAL ERROR in ProfileInversion::ReadObseravtionFile"
168  << std::endl
169  << fname << " cannot be opened.";
170  ATHENA_ERROR(msg);
171  }
172  char line[MAX_LINE], *pl;
173 
174  int rows;
175  // header
176  pl = NextLine(line, MAX_LINE, fp);
177 
178  // target values
179  sscanf(pl, "%d", &rows);
180  target->resize(rows);
181  icov->resize(rows, rows);
182 
183  for (int i = 0; i < rows; ++i) {
184  pl = NextLine(line, MAX_LINE, fp);
185  sscanf(pl, "%lf", &(*target)(i));
186  }
187 
188  // inverse covariance matrix
189  char *saveptr;
190  for (int i = 0; i < rows; ++i) {
191  pl = NextLine(line, MAX_LINE, fp);
192  char *p = strtok_r(pl, " ", &saveptr);
193  for (int j = 0; j < rows; ++j) {
194  sscanf(p, "%lf", &(*icov)(i, j));
195  p = strtok_r(NULL, " ", &saveptr);
196  }
197  }
198 
199  fclose(fp);
200 }
201 #undef MAX_LINE
202 
203 void gather_probability(std::vector<Inversion *> const &fitq) {
204  auto qlast = fitq[fitq.size() - 1];
205 
206  // replace the log probability by the last one
207  for (auto q : fitq) {
208  int nwalker = q->GetWalkers();
209 
210  for (int k = 0; k < nwalker; ++k) {
211  q->SetLogProbability(k, qlast->GetLogProbability(k));
212  }
213  }
214 }
215 } // namespace InversionHelper
Real * zz_
Definition: inversion.hpp:106
void InitializeChain(int nstep, int nwalker, int ndim, int nvalue)
Definition: inversion.cpp:71
Eigen::VectorXd target_
Definition: inversion.hpp:84
bool fit_differential_
Definition: inversion.hpp:91
virtual ~Inversion()
Definition: inversion.cpp:61
mcmc_opts opts_
Definition: inversion.hpp:101
void MakeMCMCOutputs(std::string fname)
Definition: inversion.cpp:79
Eigen::MatrixXd icov_
Definition: inversion.hpp:85
Real ** init_pos_
Definition: inversion.hpp:88
bool mcmc_initialized_
Definition: inversion.hpp:103
void ResetChain()
Definition: inversion.cpp:89
Inversion(MeshBlock *pmb, ParameterInput *pin, std::string name)
Constructor and destructor.
Definition: inversion.cpp:25
mcmc_recs recs_
Definition: inversion.hpp:102
Real * par_
Definition: inversion.hpp:106
static AllInversions Create(MeshBlock *pmb, ParameterInput *pin)
Definition: inversion.cpp:124
char * NextLine(char *line, int num, FILE *stream)
Definition: fileio.cpp:93
#define MAX_LINE
Definition: inversion.cpp:161
std::shared_ptr< Inversion > InversionPtr
Definition: inversion.hpp:109
std::vector< std::shared_ptr< Inversion > > AllInversions
Definition: inversion.hpp:110
void mcmc_free(mcmc_recs *recs)
Definition: mcmc.cpp:151
void mcmc_alloc(mcmc_recs *recs, int nstep, int nwalker, int ndim, int nvalue)
Definition: mcmc.cpp:126
void mcmc_save_fits(char const *fname, mcmc_opts *opts, mcmc_recs *recs, int include_last)
Definition: mcmc.cpp:179
void read_observation_file(Eigen::VectorXd *target, Eigen::MatrixXd *icov, std::string fname)
Definition: inversion.cpp:162
void gather_probability(std::vector< Inversion * > const &fitq)
Definition: inversion.cpp:203
void FreeCArray(T **a)
Definition: ndarrays.hpp:13
int print
Definition: mcmc.hpp:40
int p
Definition: mcmc.hpp:38
char logfile[80]
Definition: mcmc.hpp:41
double a
Definition: mcmc.hpp:37
double *** val
Definition: mcmc.hpp:56
int ** newstate
Definition: mcmc.hpp:62
int nstep
Definition: mcmc.hpp:53
int reset
Definition: mcmc.hpp:66
int ndim
Definition: mcmc.hpp:50
int nvalue
Definition: mcmc.hpp:51
double ** lnp
Definition: mcmc.hpp:57
int cur
Definition: mcmc.hpp:64
int nwalker
Definition: mcmc.hpp:52
double *** par
Definition: mcmc.hpp:55