Function createDiagonalOp

Source
pub unsafe extern "C" fn createDiagonalOp(
    numQubits: c_int,
    env: QuESTEnv,
) -> DiagonalOp
Expand description

Creates a ::DiagonalOp representing a diagonal operator on the full Hilbert space of a ::Qureg.

The resulting operator need not be unitary nor Hermitian, and can be applied to any ::Qureg of a compatible number of qubits.

This function allocates space for \f$2^{\text{numQubits}}\f$ complex amplitudes, which are initially zero. This is the same cost as a local state-vector of equal number of qubits; see the Serial section of createQureg(). Note that this is a paralell data-type, so its ultimate memory costs depend on the hardware backends, as elaborated below.

The operator elements should be modified with initDiagonalOp() and setDiagonalOpElems(), and must be later freed with destroyDiagonalOp().

§GPU

In GPU-accelerated mode, this function also creates additional equally-sized persistent memory on the GPU. If you wish to modify the operator elements directly (in lieu of setDiagonalOpElems()), you must thereafter call syncDiagonalOp() to update the operator stored in VRAM.

For example,

DiagonalOp op = createDiagonalOp(4, env);
for (long long int i=0; i<op.numElemsPerChunk; i++) {
    op.real[i] = rand();
    op.imag[i] = rand();
}
syncDiagonalOp(op);

§Distribution

In distributed mode, the memory for the diagonal operator is divided evenly between the \f$N\f$ available nodes, such that each node contains only \f$2^{\text{numQubits}}/N\f$ complex values. This is assigned to DiagonalOp.numElemsPerChunk.

Users must therefore exercise care in modifying DiagonalOp.real and DiagonalOp.imag directly.

For example, the following is valid code when when distributed between N = 2 nodes:

     // create diag({1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16})
     int numQubits = 4;
     DiagonalOp op = createDiagonalOp(numQubits, env);
     for (int i=0; i<8; i++) {
         if (env.rank == 0)
             op.real[i] = (i+1);
         if (env.rank == 1)
             op.real[i] = (i+1+8);
     }

\n

@see

  • createDiagonalOpFromPauliHamilFile()
  • setDiagonalOpElems()
  • initDiagonalOp()
  • syncDiagonalOp()
  • applyDiagonalOp()
  • calcExpecDiagonalOp()
  • destroyDiagonalOp()

@ingroup type @returns a dynamic DiagonalOp instance initialised to diag(0,0,…). @param[in] numQubits number of qubits which inform the Hilbert dimension of the operator. @param[in] env the ::QuESTEnv @throws invalidQuESTInputError()

  • if \p numQubits <= 0
  • if \p numQubits is so large that the number of elements cannot fit in a long long int type,
  • if in distributed mode, there are more nodes than elements in the operator @throws exit
  • if the memory could not be allocated @author Tyson Jones