xolotl/solver/src/monitor/Monitor1D.cpp
/**
 * This is a monitoring method that will compute the data to send to TRIDYN
 */
This is a monitoring method that will compute the data to send to TRIDYN
This is a monitoring method that will compute the data to send to TRIDYN
PetscErrorCode
computeTRIDYN1D(
	TS ts, PetscInt timestep, PetscReal time, Vec solution, void* ictx)
{
	perf::ScopedTimer myTimer(tridynTimer);
	PetscErrorCode ierr;
	IdType xs, xm, Mx, ys, ym, My, zs, zm, Mz;
	PetscFunctionBeginUser;
	auto xolotlComm = util::getMPIComm();
	auto& solverHandler = PetscSolver::getSolverHandler();
	solverHandler.getLocalCoordinates(xs, xm, Mx, ys, ym, My, zs, zm, Mz);
	auto& network = solverHandler.getNetwork();
	const auto dof = network.getDOF();
	const auto numSpecies = network.getSpeciesListSize();
	auto surfacePos = static_cast<PetscInt>(solverHandler.getSurfacePosition());
	DM da;
	ierr = TSGetDM(ts, &da);
	CHKERRQ(ierr);
	auto grid = solverHandler.getXGrid();
	PetscReal** solutionArray;
	ierr = DMDAVecGetArrayDOFRead(da, solution, &solutionArray);
	CHKERRQ(ierr);
	 First create the file for parallel file access.
	std::ostringstream tdFileStr;
	tdFileStr << "TRIDYN_" << timestep << ".h5";
	io::HDF5File tdFile(tdFileStr.str(),
		io::HDF5File::AccessMode::CreateOrTruncateIfExists, xolotlComm, true);
	 Define a dataset for concentrations.
	 Everyone must create the dataset with the same shape.
	const auto numValsPerGridpoint = 5 + 2;
	const auto firstIdxToWrite = (surfacePos + solverHandler.getLeftOffset());
	const auto numGridpointsWithConcs = (Mx - firstIdxToWrite);
	io::HDF5File::SimpleDataSpace<2>::Dimensions concsDsetDims = {
		(hsize_t)numGridpointsWithConcs, numValsPerGridpoint};
	io::HDF5File::SimpleDataSpace<2> concsDsetSpace(concsDsetDims);
	const std::string concsDsetName = "concs";
	io::HDF5File::DataSet<double> concsDset(
		tdFile, concsDsetName, concsDsetSpace);
	 Specify the concentrations we will write.
	 We only consider our own grid points.
	const auto myFirstIdxToWrite =
		std::max((IdType)xs, (IdType)firstIdxToWrite);
	auto myEndIdx = (xs + xm);  "end" in the C++ sense; i.e., one-past-last
	auto myNumPointsToWrite =
		(myEndIdx > myFirstIdxToWrite) ? (myEndIdx - myFirstIdxToWrite) : 0;
	io::HDF5File::DataSet<double>::DataType2D<numValsPerGridpoint> myConcs(
		myNumPointsToWrite);
	for (auto xi = myFirstIdxToWrite; xi < myEndIdx; ++xi) {
		if (xi >= firstIdxToWrite) {
			 Determine current gridpoint value.
			double x = (grid[xi] + grid[xi + 1]) / 2.0 - grid[1];
			 Access the solution data for this grid point.
			auto gridPointSolution = solutionArray[xi];
			using HostUnmanaged = Kokkos::View<double*, Kokkos::HostSpace,
				Kokkos::MemoryUnmanaged>;
			auto hConcs = HostUnmanaged(gridPointSolution, dof);
			auto dConcs = Kokkos::View<double*>("Concentrations", dof);
			deep_copy(dConcs, hConcs);
			 Get the total concentrations at this grid point
			auto currIdx = (PetscInt)xi - myFirstIdxToWrite;
			myConcs[currIdx][0] = (x - (grid[surfacePos + 1] - grid[1]));
			 Get the total concentrations at this grid point
			for (auto id = core::network::SpeciesId(numSpecies); id; ++id) {
				myConcs[currIdx][id() + 1] +=
					network.getTotalAtomConcentration(dConcs, id, 1);
			}
			myConcs[currIdx][6] = gridPointSolution[dof];
		}
	}
	 Write the concs dataset in parallel.
	 (We write only our part.)
	concsDset.parWrite2D<numValsPerGridpoint>(
		xolotlComm, myFirstIdxToWrite - firstIdxToWrite, myConcs);
	 Restore the solutionArray
	ierr = DMDAVecRestoreArrayDOFRead(da, solution, &solutionArray);
	CHKERRQ(ierr);
	PetscFunctionReturn(0);
}
PetscErrorCode computeTRIDYN1D ( TS ts , PetscInt timestep , PetscReal time , Vec solution , void * ictx ) { perf :: ScopedTimer myTimer ( tridynTimer ) ; PetscErrorCode ierr ; IdType xs , xm , Mx , ys , ym , My , zs , zm , Mz ; PetscFunctionBeginUser ; auto xolotlComm = util :: getMPIComm ( ) ; auto & solverHandler = PetscSolver :: getSolverHandler ( ) ; solverHandler . getLocalCoordinates ( xs , xm , Mx , ys , ym , My , zs , zm , Mz ) ; auto & network = solverHandler . getNetwork ( ) ; const auto dof = network . getDOF ( ) ; const auto numSpecies = network . getSpeciesListSize ( ) ; auto surfacePos = static_cast < PetscInt > ( solverHandler . getSurfacePosition ( ) ) ; DM da ; ierr = TSGetDM ( ts , & da ) ; CHKERRQ ( ierr ) ; auto grid = solverHandler . getXGrid ( ) ; PetscReal * * solutionArray ; ierr = DMDAVecGetArrayDOFRead ( da , solution , & solutionArray ) ; CHKERRQ ( ierr ) ; std :: ostringstream tdFileStr ; tdFileStr << " " << timestep << " " ; io :: HDF5File tdFile ( tdFileStr . str ( ) , io :: HDF5File :: AccessMode :: CreateOrTruncateIfExists , xolotlComm , true ) ; const auto numValsPerGridpoint = 5 + 2 ; const auto firstIdxToWrite = ( surfacePos + solverHandler . getLeftOffset ( ) ) ; const auto numGridpointsWithConcs = ( Mx - firstIdxToWrite ) ; io :: HDF5File :: SimpleDataSpace < 2 > :: Dimensions concsDsetDims = { ( hsize_t ) numGridpointsWithConcs , numValsPerGridpoint } ; io :: HDF5File :: SimpleDataSpace < 2 > concsDsetSpace ( concsDsetDims ) ; const std :: string concsDsetName = " " ; io :: HDF5File :: DataSet < double > concsDset ( tdFile , concsDsetName , concsDsetSpace ) ; const auto myFirstIdxToWrite = std :: max ( ( IdType ) xs , ( IdType ) firstIdxToWrite ) ; auto myEndIdx = ( xs + xm ) ; auto myNumPointsToWrite = ( myEndIdx > myFirstIdxToWrite ) ? ( myEndIdx - myFirstIdxToWrite ) : 0 ; io :: HDF5File :: DataSet < double > :: DataType2D < numValsPerGridpoint > myConcs ( myNumPointsToWrite ) ; for ( auto xi = myFirstIdxToWrite ; xi < myEndIdx ; ++ xi ) { if ( xi >= firstIdxToWrite ) { double x = ( grid [ xi ] + grid [ xi + 1 ] ) / 2.0 - grid [ 1 ] ; auto gridPointSolution = solutionArray [ xi ] ; using HostUnmanaged = Kokkos :: View < double * , Kokkos :: HostSpace , Kokkos :: MemoryUnmanaged > ; auto hConcs = HostUnmanaged ( gridPointSolution , dof ) ; auto dConcs = Kokkos :: View < double * > ( " " , dof ) ; deep_copy ( dConcs , hConcs ) ; auto currIdx = ( PetscInt ) xi - myFirstIdxToWrite ; myConcs [ currIdx ] [ 0 ] = ( x - ( grid [ surfacePos + 1 ] - grid [ 1 ] ) ) ; for ( auto id = core :: network :: SpeciesId ( numSpecies ) ; id ; ++ id ) { myConcs [ currIdx ] [ id ( ) + 1 ] += network . getTotalAtomConcentration ( dConcs , id , 1 ) ; } myConcs [ currIdx ] [ 6 ] = gridPointSolution [ dof ] ; } } concsDset . parWrite2D < numValsPerGridpoint > ( xolotlComm , myFirstIdxToWrite - firstIdxToWrite , myConcs ) ; ierr = DMDAVecRestoreArrayDOFRead ( da , solution , & solutionArray ) ; CHKERRQ ( ierr ) ; PetscFunctionReturn ( 0 ) ; }
This is a monitoring method that will compute the data to send to TRIDYN
This is a monitoring method that will compute the data to send to TRIDYN
// Initial declarations // Get the MPI communicator // Get the solver handler and local coordinates // Get the network // Get the position of the surface // Get the da from ts // Get the physical grid // Get the array of concentration // Save current concentrations as an HDF5 file. // // First create the file for parallel file access. // Define a dataset for concentrations. // Everyone must create the dataset with the same shape. // Specify the concentrations we will write. // We only consider our own grid points. // "end" in the C++ sense; i.e., one-past-last // Determine current gridpoint value. // Access the solution data for this grid point. // Get the total concentrations at this grid point // Get the total concentrations at this grid point // Write the concs dataset in parallel. // (We write only our part.) // Restore the solutionArray