Skip to content

Commit 55a1ac4

Browse files
committed
Compute trajectory output only if requested in the config.
Previously, trajectory output for the expected energy level and the population were computed even though they were not written to files, which increases compute time because this is done at each time step. Now, the values are only computed if the user had requested this output in the configuration file. The configuration string is parsed in the constructor of the Output class, which stores booleans to determine which output was requested by the user. If booleans are true, the 0-th petsc rank opens the files, writes the data per timestep, and closes the files. Note that computing reduced output values per oscillator require an MPI allreduce over all petsc ranks. Hence, all petsc ranks need to compute the output whereas only the 0-th rank writes them to the open file.
1 parent 75fdcf6 commit 55a1ac4

File tree

3 files changed

+93
-84
lines changed

3 files changed

+93
-84
lines changed

include/output.hpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,19 @@ class Output{
1919
int output_frequency; /* Output frequency in time domain: write output at every <num> time step. */
2020
std::vector<std::vector<std::string> > outputstr; // List of outputs for each oscillator
2121

22-
bool writefullstate; /* Flag to determin if full state vector should be written to file */
22+
bool writeFullState; /* Flag to determine if full state vector should be written to file */
2323
FILE *ufile; /* File for writing real part of solution vector */
2424
FILE *vfile; /* File for writing imaginary part of solution vector */
25-
std::vector<FILE *>expectedfile; /* Files for writing the evolution of the expected energy levels per oscillator */
26-
FILE *expectedfile_comp; /* File for writing the evolution of the expected energy level of the composite system */
27-
FILE *populationfile_comp; /* File for writing the evolution of the population of the composite system */
25+
26+
std::vector<bool> writeExpectedEnergy; ///< Flag to determine if the evolution of the expected energy per oscillator should be written to files.
27+
bool writeExpectedEnergy_comp; ///< Flag to determine if the evolution of the expected energy of the full composite system should be written to file
28+
std::vector<FILE *>expectedfile; /* Files for writing the evolution of the expected energy per oscillator */
29+
FILE *expectedfile_comp; /* File for writing the evolution of the expected energy level of the full composite system */
30+
31+
std::vector<bool> writePopulation; ///< Flag to determine if the evolution of the energy level occupations per oscillator should be written to files.
32+
bool writePopulation_comp; ///< Flag to determine if the evolution of the energy level occupations of the full composite system should be written to file
2833
std::vector<FILE *>populationfile; /* Files for writing population over time */
34+
FILE *populationfile_comp; /* File for writing the evolution of the population of the composite system */
2935

3036
// VecScatter scat; /* Petsc's scatter context to communicate a state across petsc's cores */
3137
// Vec xseq; /* A sequential vector for IO. */

src/output.cpp

Lines changed: 82 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -36,35 +36,44 @@ Output::Output(MapParam& config, MPI_Comm comm_petsc, MPI_Comm comm_init, int no
3636
fprintf(optimfile, "#\"iter\" \"Objective\" \"||Pr(grad)||\" \"LS step\" \"F_avg\" \"Terminal cost\" \"Tikhonov-regul\" \"Penalty-term\" \"State variation\" \"Energy-term\" \"Control variation\"\n");
3737
}
3838

39-
/* Read from config what output is desired */
39+
/* Reset flags and data file pointers */
40+
ufile = NULL;
41+
vfile = NULL;
42+
for (int i=0; i< noscillators; i++) expectedfile.push_back (NULL);
43+
for (int i=0; i< noscillators; i++) populationfile.push_back (NULL);
44+
expectedfile_comp=NULL;
45+
populationfile_comp=NULL;
46+
writeFullState = false;
47+
writeExpectedEnergy_comp = false;
48+
writePopulation_comp = false;
49+
for (int i=0; i<noscillators; i++) writeExpectedEnergy.push_back(false);
50+
for (int i=0; i<noscillators; i++) writePopulation.push_back(false);
51+
52+
/* Parse configuration output strings for each oscillator and set defaults. */
4053
for (int i = 0; i < noscillators; i++){
4154
std::vector<std::string> fillme;
4255
config.GetVecStrParam("output" + std::to_string(i), fillme, "none");
4356
outputstr.push_back(fillme);
4457
}
4558

46-
/* Search through outputstrings to see if any oscillator contains "fullstate" */
47-
writefullstate = false;
48-
for (size_t i=0; i<outputstr.size(); i++) {
49-
for (size_t j=0; j<outputstr[i].size(); j++) {
50-
if (outputstr[i][j].compare("fullstate") == 0 ) writefullstate = true;
59+
/* Check the output strings for each oscillator to determine which files should be written */
60+
for (int i=0; i<noscillators; i++) { // iterates over oscillators
61+
for (size_t j=0; j<outputstr[i].size(); j++) { // iterates over output stings for this oscillator
62+
if (outputstr[i][j].compare("expectedEnergy") == 0) writeExpectedEnergy[i] = true;
63+
if (outputstr[i][j].compare("expectedEnergyComposite") == 0) writeExpectedEnergy_comp = true;
64+
if (outputstr[i][j].compare("population") == 0) writePopulation[i] = true;
65+
if (outputstr[i][j].compare("populationComposite") == 0) writePopulation_comp = true;
66+
if (outputstr[i][j].compare("fullstate") == 0 ) writeFullState = true;
5167
}
5268
}
53-
54-
/* Prepare data output files */
55-
ufile = NULL;
56-
vfile = NULL;
57-
for (size_t i=0; i< outputstr.size(); i++) expectedfile.push_back (NULL);
58-
for (size_t i=0; i< outputstr.size(); i++) populationfile.push_back (NULL);
59-
expectedfile_comp=NULL;
60-
populationfile_comp=NULL;
61-
6269
}
6370

6471

6572
Output::~Output(){
6673
if (mpirank_world == 0 && !quietmode) printf("Output directory: %s\n", datadir.c_str());
6774
if (mpirank_world == 0) fclose(optimfile);
75+
writeExpectedEnergy.clear();
76+
writePopulation.clear();
6877
}
6978

7079

@@ -74,7 +83,6 @@ void Output::writeOptimFile(int optim_iter, double objective, double gnorm, doub
7483
fprintf(optimfile, "%05d %1.14e %1.14e %.8f %1.14e %1.14e %1.14e %1.14e %1.14e %1.14e %1.14e\n", optim_iter, objective, gnorm, stepsize, Favg, costT, tikh_regul, penalty, penalty_dpdm, penalty_energy, penalty_variation);
7584
fflush(optimfile);
7685
}
77-
7886
}
7987

8088
void Output::writeGradient(Vec grad){
@@ -151,107 +159,102 @@ void Output::writeControls(Vec params, MasterEq* mastereq, int ntime, double dt)
151159
void Output::openDataFiles(std::string prefix, int initid){
152160
char filename[255];
153161

154-
/* Flag to determine if this optimization iteration will write data output */
155-
156-
/* Open files for state vector */
157-
if (mpirank_petsc == 0 && writefullstate ) {
158-
snprintf(filename, 254, "%s/%s_Re.iinit%04d.dat", datadir.c_str(), prefix.c_str(), initid);
159-
ufile = fopen(filename, "w");
160-
snprintf(filename, 254, "%s/%s_Im.iinit%04d.dat", datadir.c_str(), prefix.c_str(), initid);
161-
vfile = fopen(filename, "w");
162-
}
163-
164-
/* Open files for expected energy */
165-
bool writeExpComp = false;
166-
bool writePopComp = false;
162+
// On the first petsc rank, open required files and print header information
167163
if (mpirank_petsc == 0) {
168-
for (size_t i=0; i<outputstr.size(); i++) {
169-
for (size_t j=0; j<outputstr[i].size(); j++) {
170-
if (outputstr[i][j].compare("expectedEnergy") == 0) {
171-
snprintf(filename, 254, "%s/expected%zu.iinit%04d.dat", datadir.c_str(), i, initid);
172-
expectedfile[i] = fopen(filename, "w");
173-
fprintf(expectedfile[i], "#\"time\" \"expected energy level\"\n");
174-
}
175-
if (outputstr[i][j].compare("expectedEnergyComposite") == 0) writeExpComp = true;
176-
if (outputstr[i][j].compare("population") == 0) {
177-
snprintf(filename, 254, "%s/population%zu.iinit%04d.dat", datadir.c_str(), i, initid);
178-
populationfile[i] = fopen(filename, "w");
179-
fprintf(populationfile[i], "#\"time\" \"diagonal of the density matrix\"\n");
180-
}
181-
if (outputstr[i][j].compare("populationComposite") == 0) writePopComp = true;
164+
165+
// Expected energy per oscillator
166+
for (size_t i=0; i<outputstr.size(); i++) { // iterates over oscillators
167+
if (writeExpectedEnergy[i]) {
168+
snprintf(filename, 254, "%s/expected%zu.iinit%04d.dat", datadir.c_str(), i, initid);
169+
expectedfile[i] = fopen(filename, "w");
170+
fprintf(expectedfile[i], "#\"time\" \"expected energy level\"\n");
182171
}
183172
}
184-
if (writeExpComp){
173+
// Expected energy for full composite system
174+
if (writeExpectedEnergy_comp) {
185175
snprintf(filename, 254, "%s/expected_composite.iinit%04d.dat", datadir.c_str(), initid);
186176
expectedfile_comp = fopen(filename, "w");
187177
fprintf(expectedfile_comp, "#\"time\" \"expected energy level\"\n");
188178
}
189-
if (writePopComp){
179+
// Populations per oscillator
180+
for (size_t i=0; i<outputstr.size(); i++) { // iterates over oscillators
181+
if (writePopulation[i]) {
182+
snprintf(filename, 254, "%s/population%zu.iinit%04d.dat", datadir.c_str(), i, initid);
183+
populationfile[i] = fopen(filename, "w");
184+
fprintf(populationfile[i], "#\"time\" \"diagonal of the density matrix\"\n");
185+
}
186+
}
187+
// Population for full composite system
188+
if (writePopulation_comp) {
190189
snprintf(filename, 254, "%s/population_composite.iinit%04d.dat", datadir.c_str(), initid);
191190
populationfile_comp = fopen(filename, "w");
192191
fprintf(populationfile_comp, "#\"time\" \"population\"\n");
193192
}
194-
193+
// Full vectorized state
194+
if (writeFullState ) {
195+
snprintf(filename, 254, "%s/%s_Re.iinit%04d.dat", datadir.c_str(), prefix.c_str(), initid);
196+
ufile = fopen(filename, "w");
197+
snprintf(filename, 254, "%s/%s_Im.iinit%04d.dat", datadir.c_str(), prefix.c_str(), initid);
198+
vfile = fopen(filename, "w");
199+
}
195200
}
196-
197201
}
198202

199203
void Output::writeDataFiles(int timestep, double time, const Vec state, MasterEq* mastereq){
200204

201205
/* Write output only every <num> time-steps */
202206
if (timestep % output_frequency == 0) {
203207

204-
205208
/* Write expected energy levels to file */
206209
for (size_t iosc = 0; iosc < expectedfile.size(); iosc++) {
207-
double expected = mastereq->getOscillator(iosc)->expectedEnergy(state);
208-
if (expectedfile[iosc] != NULL) {
209-
fprintf(expectedfile[iosc], "%.8f %1.14e\n", time, expected);
210+
if (writeExpectedEnergy[iosc]) {
211+
double expected = mastereq->getOscillator(iosc)->expectedEnergy(state);
212+
if (mpirank_petsc==0) fprintf(expectedfile[iosc], "%.8f %1.14e\n", time, expected);
210213
}
211214
}
212-
213-
double expected_comp = mastereq->expectedEnergy(state);
214-
if (expectedfile_comp != NULL) {
215-
fprintf(expectedfile_comp, "%.8f %1.14e\n", time, expected_comp);
215+
if (writeExpectedEnergy_comp) {
216+
double expected_comp = mastereq->expectedEnergy(state);
217+
if (mpirank_petsc==0) fprintf(expectedfile_comp, "%.8f %1.14e\n", time, expected_comp);
216218
}
217219

218220
/* Write population to file */
219221
for (size_t iosc = 0; iosc < populationfile.size(); iosc++) {
220-
std::vector<double> pop (mastereq->getOscillator(iosc)->getNLevels(), 0.0);
221-
mastereq->getOscillator(iosc)->population(state, pop);
222-
if (populationfile[iosc] != NULL) {
223-
fprintf(populationfile[iosc], "%.8f ", time);
224-
for (size_t i = 0; i<pop.size(); i++) {
225-
fprintf(populationfile[iosc], " %1.14e", pop[i]);
222+
if (writePopulation[iosc]) {
223+
std::vector<double> pop (mastereq->getOscillator(iosc)->getNLevels(), 0.0);
224+
mastereq->getOscillator(iosc)->population(state, pop);
225+
if (mpirank_petsc == 0) {
226+
fprintf(populationfile[iosc], "%.8f ", time);
227+
for (size_t i = 0; i<pop.size(); i++) {
228+
fprintf(populationfile[iosc], " %1.14e", pop[i]);
229+
}
230+
fprintf(populationfile[iosc], "\n");
226231
}
227-
fprintf(populationfile[iosc], "\n");
228232
}
229233
}
230-
231-
std::vector<double> population_comp;
232-
mastereq->population(state, population_comp);
233-
if (populationfile_comp != NULL) {
234-
fprintf(populationfile_comp, "%.8f ", time);
235-
for (size_t i=0; i<population_comp.size(); i++){
236-
fprintf(populationfile_comp, "%1.14e ", population_comp[i]);
234+
if (writePopulation_comp) {
235+
std::vector<double> population_comp;
236+
mastereq->population(state, population_comp);
237+
if (mpirank_petsc == 0) {
238+
fprintf(populationfile_comp, "%.8f ", time);
239+
for (size_t i=0; i<population_comp.size(); i++){
240+
fprintf(populationfile_comp, "%1.14e ", population_comp[i]);
241+
}
242+
fprintf(populationfile_comp, "\n");
237243
}
238-
fprintf(populationfile_comp, "\n");
239244
}
240245

241-
/* Write full state to file */
242-
if (writefullstate && mpisize_petsc == 1) {
243-
246+
/* Write full state to file. Currently not available if Petsc-parallel */
247+
if (writeFullState && mpisize_petsc == 1) {
244248
/* TODO: Make this work in parallel! */
245249
/* Gather the vector from all petsc processors onto the first one */
246250
// VecScatterCreateToZero(x, &scat, &xseq);
247251
// VecScatterBegin(scat, u->x, xseq, INSERT_VALUES, SCATTER_FORWARD);
248252
// VecScatterEnd(scat, u->x, xseq, INSERT_VALUES, SCATTER_FORWARD);
249253

250-
/* Write full state vector to file */
251-
if (ufile != NULL && vfile != NULL) {
254+
/* On first petsc rank, write full state vector to file */
255+
if (mpirank_petsc == 0) {
252256
fprintf(ufile, "%.8f ", time);
253257
fprintf(vfile, "%.8f ", time);
254-
255258
const PetscScalar *x;
256259
VecGetArrayRead(state, &x);
257260
for (int i=0; i<mastereq->getDim(); i++) {
@@ -262,9 +265,9 @@ void Output::writeDataFiles(int timestep, double time, const Vec state, MasterEq
262265
fprintf(vfile, "\n");
263266
VecRestoreArrayRead(state, &x);
264267
}
265-
/* Destroy scatter context and vector */
266-
// VecScatterDestroy(&scat);
267-
// VecDestroy(&xseq); // TODO create and destroy scatter and xseq in contructor/destructor
268+
/* Destroy scatter context and vector */
269+
// VecScatterDestroy(&scat);
270+
// VecDestroy(&xseq); // TODO create and destroy scatter and xseq in contructor/destructor
268271
}
269272
}
270273
}

tests/regression/nlevels_4_4_4_4/nlevels_4_4_4_4.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ optim_penalty_energy= 0.0
4444
optim_penalty_variation= 0.0
4545
optim_regul_tik0=false
4646
datadir = ./data_out
47-
output0 = expectedEnergy, population
47+
output0 = expectedEnergy, population, expectedEnergyComposite, populationComposite
4848
output1 = expectedEnergy, population
4949
output2 = expectedEnergy, population
5050
output3 = expectedEnergy, population

0 commit comments

Comments
 (0)