116 const int useDistrib = 1;
117 const bool userOwnsMpi =
true;
120 validate_mpiInitStatus(useDistrib, userOwnsMpi, __func__);
121 validate_mpiSubCommIsNonNull(userQuestComm != MPI_COMM_NULL, __func__);
126 if (!comm_isActive()) {
127 bool success = comm_setMpiComm(userQuestComm, userOwnsMpi);
128 validate_mpiSubCommSetSucceeded(success, __func__);
132 validateAndInitCustomQuESTEnv(useDistrib, userOwnsMpi, useGpuAccel, useMultithread, __func__);
156 validate_adios2IsCompiled(__func__);
157 validate_quregFields(qureg, __func__);
161#if QUEST_COMPILE_ADIOS2
167 bool shouldSkipAdios = (! qureg.isDistributed) && (comm_getRank() > ROOT_RANK);
170 if (qureg.isDistributed)
176 if (qureg.isGpuAccelerated)
177 gpu_copyGpuToCpu(qureg);
180 adios2::ADIOS adios = createAdios(qureg.isDistributed);
181 adios2::IO io = adios.DeclareIO(
"QuESTQuregSave");
187 adios2::Engine engine;
188 bool success =
false;
190 if (!shouldSkipAdios)
191 engine = io.Open(fn, adios2::Mode::Write);
194 validate_adiosCanOpenFileOnAllNodes(success, fn, __func__);
199 adios2::Variable<int> vNumQubits = io.DefineVariable<
int>(
"numQubits");
200 adios2::Variable<int> vNumNodes = io.DefineVariable<
int>(
"numNodes");
201 adios2::Variable<int> vIsDensMatr = io.DefineVariable<
int>(
"isDensityMatrix");
202 adios2::Variable<size_t> vQrealBytes = io.DefineVariable<
size_t>(
"qrealBytes");
208 qindex globalReals = 2 * qureg.numAmps;
209 qindex localReals = 2 * qureg.numAmpsPerNode;
210 qindex startReal = localReals * qureg.rank;
211 adios2::Variable<qreal> vAmpComponents = io.DefineVariable<qreal>(
213 { (size_t) globalReals },
214 { (size_t) startReal },
215 { (size_t) localReals });
220 if (!shouldSkipAdios) {
221 engine.Put(vNumQubits, qureg.numQubits);
222 engine.Put(vNumNodes, qureg.numNodes);
223 engine.Put(vIsDensMatr, qureg.isDensityMatrix);
224 engine.Put(vQrealBytes,
sizeof(qreal));
225 engine.Put(vAmpComponents,
reinterpret_cast<qreal*
>(qureg.cpuAmps));
230 validate_adiosCanWriteToFileOnAllNodes(success, fn, __func__);
233 if (qureg.isDistributed)
241 validate_adios2IsCompiled(__func__);
243#if QUEST_COMPILE_ADIOS2
252 bool giveAdiosMpi = comm_isActive();
255 adios2::ADIOS adios = createAdios(giveAdiosMpi);
256 adios2::IO io = adios.DeclareIO(
"QuESTQuregLoad");
262 adios2::Engine engine;
263 bool success =
false;
265 engine = io.Open(fn, adios2::Mode::ReadRandomAccess);
268 validate_adiosCanOpenFileOnAllNodes(success, fn, __func__);
271 auto vNumQubits = io.InquireVariable<
int>(
"numQubits");
272 auto vNumNodes = io.InquireVariable<
int>(
"numNodes");
273 auto vIsDensMatr = io.InquireVariable<
int>(
"isDensityMatrix");
274 auto vQrealBytes = io.InquireVariable<
size_t>(
"qrealBytes");
275 auto vAmpComponents = io.InquireVariable<qreal>(
"ampComponents");
276 bool areAllVarsPresent = vNumQubits && vNumNodes && vIsDensMatr && vQrealBytes && vAmpComponents;
277 validate_adiosFileContainsFieldsOnAllNodes(areAllVarsPresent, __func__);
283 size_t fileQrealBytes = 0;
286 engine.Get(vNumQubits, numQubits);
287 engine.Get(vNumNodes, numNodes);
288 engine.Get(vIsDensMatr, isDensMatr);
289 engine.Get(vQrealBytes, fileQrealBytes);
290 engine.PerformGets();
293 validate_adiosCanReadFileOnAllNodes(success, fn, __func__);
296 validate_newQuregFileMatchesPrecision(fileQrealBytes, __func__);
299 Qureg qureg = validateAndCreateCustomQureg(numQubits, isDensMatr,
300 modeflag::USE_AUTO, modeflag::USE_AUTO, modeflag::USE_AUTO, __func__);
303 if (qureg.numNodes != numNodes)
305 validate_newQuregNumNodesMatchesSavedFile(numNodes, qureg.numNodes, comm_getNumNodes(), numQubits, isDensMatr, __func__);
309 qindex localReals = 2 * qureg.numAmpsPerNode;
310 qindex startReal = 2 * ((qindex) qureg.rank) * qureg.numAmpsPerNode;
311 vAmpComponents.SetSelection({ { (size_t) startReal }, { (size_t) localReals } });
314 engine.Get(vAmpComponents,
reinterpret_cast<qreal*
>(qureg.cpuAmps));
317 validate_adiosCanReadFileOnAllNodes(success, fn, __func__);
325 validate_adiosCanReadFileOnAllNodes(success, fn, __func__);
328 if (qureg.isGpuAccelerated)
329 gpu_copyCpuToGpu(qureg);