xolotl/solver/src/monitor/Monitor.cpp
/**
 * This is a monitoring method that will save 1D plots of one performance timer
 */
This is a monitoring method that will save 1D plots of one performance timer
This is a monitoring method that will save 1D plots of one performance timer
PetscErrorCode
monitorPerf(TS ts, PetscInt timestep, PetscReal time, Vec, void*)
{
	PetscErrorCode ierr;
	PetscFunctionBeginUser;
	auto xolotlComm = util::getMPIComm();
	int cwSize;
	int cwRank;
	MPI_Comm_size(xolotlComm, &cwSize);
	MPI_Comm_rank(xolotlComm, &cwRank);
	if (cwSize == 1) {
		std::cout
			<< "You are trying to plot things that don't have any sense!! "
			<< "\nRemove -plot_perf or run in parallel." << std::endl;
		PetscFunctionReturn(0);
	}
	 Note that the solve timer keeps a cumulative time,
	 not a per-timestep time.   If you need a per-timestep
	 time, you will want to keep a static or global variable
	 with the last known timer value, and subtract it from
	 the current timer value each time this monitor function is called.
	 Note also that we restart the timer immediately after sampling
	 its value.  If you feel it is "unfair" to charge the time
	 required for the rank 0 process to produce the output plot
	 against the solve timer, then you should move the start()
	 call after the code that produces the plot (and probably also
	 put in an MPI_Barrier before starting the timer so that
	 all processes avoid including the time required for rank 0
	 to produce the plot).  We probably don't want to reset the
	 timer here since the main function is using it to get an
	 overall elapsed time measurement of the solve.
	auto solverTimer = perf::PerfHandlerRegistry::get()->getTimer("solve");
	solverTimer->stop();
	double solverTimerValue = solverTimer->getValue();
	solverTimer->start();
	 Collect all sampled timer values to rank 0.
	std::vector<double> allTimerValues((cwRank == 0) ? cwSize : 0);
	MPI_Gather(&solverTimerValue,  send buffer
		1,  number of values to send
		MPI_DOUBLE,  type of items in send buffer
		allTimerValues.data(),  receive buffer (only valid at root)
		1,  number of values to receive from each process
		MPI_DOUBLE,  type of items in receive buffer
		0,  root of MPI collective operation
		xolotlComm);  communicator defining processes involved in the
					  operation
	if (cwRank == 0) {
		auto allPoints =
			std::make_shared<std::vector<viz::dataprovider::DataPoint>>();
		for (auto i = 0; i < cwSize; ++i) {
			viz::dataprovider::DataPoint aPoint;
			aPoint.value = allTimerValues[i];
			aPoint.x = i;
			aPoint.t = time;
			allPoints->push_back(aPoint);
		}
		 Provide the data provider the points.
		perfPlot->getDataProvider()->setDataPoints(allPoints);
		perfPlot->getDataProvider()->setDataName("SolverTimer");
		 Change the title of the plot
		std::ostringstream title;
		title << "Solver timer (s)";
		perfPlot->plotLabelProvider->titleLabel = title.str();
		 Give the time to the label provider
		std::ostringstream timeLabel;
		timeLabel << "time: " << std::setprecision(4) << time << "s";
		perfPlot->plotLabelProvider->timeLabel = timeLabel.str();
		 Get the current time step
		PetscReal currentTimeStep;
		ierr = TSGetTimeStep(ts, &currentTimeStep);
		CHKERRQ(ierr);
		 Give the timestep to the label provider
		std::ostringstream timeStepLabel;
		timeStepLabel << "dt: " << std::setprecision(4) << currentTimeStep
					  << "s";
		perfPlot->plotLabelProvider->timeStepLabel = timeStepLabel.str();
		 Render and save in file
		std::ostringstream fileName;
		fileName << "timer_TS" << timestep << ".pnm";
		perfPlot->write(fileName.str());
	}
	PetscFunctionReturn(0);
}
PetscErrorCode monitorPerf ( TS ts , PetscInt timestep , PetscReal time , Vec , void * ) { PetscErrorCode ierr ; PetscFunctionBeginUser ; auto xolotlComm = util :: getMPIComm ( ) ; int cwSize ; int cwRank ; MPI_Comm_size ( xolotlComm , & cwSize ) ; MPI_Comm_rank ( xolotlComm , & cwRank ) ; if ( cwSize == 1 ) { std :: cout << " " << " \n " << std :: endl ; PetscFunctionReturn ( 0 ) ; } auto solverTimer = perf :: PerfHandlerRegistry :: get ( ) -> getTimer ( " " ) ; solverTimer -> stop ( ) ; double solverTimerValue = solverTimer -> getValue ( ) ; solverTimer -> start ( ) ; std :: vector < double > allTimerValues ( ( cwRank == 0 ) ? cwSize : 0 ) ; MPI_Gather ( & solverTimerValue , 1 , MPI_DOUBLE , allTimerValues . data ( ) , 1 , MPI_DOUBLE , 0 , xolotlComm ) ; if ( cwRank == 0 ) { auto allPoints = std :: make_shared < std :: vector < viz :: dataprovider :: DataPoint > > ( ) ; for ( auto i = 0 ; i < cwSize ; ++ i ) { viz :: dataprovider :: DataPoint aPoint ; aPoint . value = allTimerValues [ i ] ; aPoint . x = i ; aPoint . t = time ; allPoints -> push_back ( aPoint ) ; } perfPlot -> getDataProvider ( ) -> setDataPoints ( allPoints ) ; perfPlot -> getDataProvider ( ) -> setDataName ( " " ) ; std :: ostringstream title ; title << " " ; perfPlot -> plotLabelProvider -> titleLabel = title . str ( ) ; std :: ostringstream timeLabel ; timeLabel << " " << std :: setprecision ( 4 ) << time << " " ; perfPlot -> plotLabelProvider -> timeLabel = timeLabel . str ( ) ; PetscReal currentTimeStep ; ierr = TSGetTimeStep ( ts , & currentTimeStep ) ; CHKERRQ ( ierr ) ; std :: ostringstream timeStepLabel ; timeStepLabel << " " << std :: setprecision ( 4 ) << currentTimeStep << " " ; perfPlot -> plotLabelProvider -> timeStepLabel = timeStepLabel . str ( ) ; std :: ostringstream fileName ; fileName << " " << timestep << " " ; perfPlot -> write ( fileName . str ( ) ) ; } PetscFunctionReturn ( 0 ) ; }
This is a monitoring method that will save 1D plots of one performance timer
This is a monitoring method that will save 1D plots of one performance timer
// To check PETSc errors // Get the number of processes // Print a warning if only one process // Obtain the current value of the solve timer. // // Note that the solve timer keeps a cumulative time, // not a per-timestep time.   If you need a per-timestep // time, you will want to keep a static or global variable // with the last known timer value, and subtract it from // the current timer value each time this monitor function is called. // // Note also that we restart the timer immediately after sampling // its value.  If you feel it is "unfair" to charge the time // required for the rank 0 process to produce the output plot // against the solve timer, then you should move the start() // call after the code that produces the plot (and probably also // put in an MPI_Barrier before starting the timer so that // all processes avoid including the time required for rank 0 // to produce the plot).  We probably don't want to reset the // timer here since the main function is using it to get an // overall elapsed time measurement of the solve. // // Collect all sampled timer values to rank 0. // send buffer // number of values to send // type of items in send buffer // receive buffer (only valid at root) // number of values to receive from each process // type of items in receive buffer // root of MPI collective operation // communicator defining processes involved in the // operation // Provide the data provider the points. // Change the title of the plot // Give the time to the label provider // Get the current time step // Give the timestep to the label provider // Render and save in file