/***********************************************************//** Free memory allocated to array of QR structures \param[in,out] qr - array to free \param[in] n - number of QR structures ***************************************************************/ void qr_array_free(struct QR ** qr, size_t n) { if (qr != NULL){ size_t ii; for (ii = 0; ii < n; ii++){ qr_free(qr[ii]); qr[ii] = NULL; } free(qr); qr = NULL; } }
int main(void) { // bugfix for comma in floating point outputs with printf gtk_disable_setlocale(); gtk_init(NULL, NULL); gtk_window_init(); gtk_main(); qr_free(); return 0; }
/***********************************************************//** Perform a right-left dmrg sweep as part of ft-product \param[in] z - initial guess \param[in] f - specialized function to multiply core by matrix \param[in] args - arguments to f \param[in,out] phil - left multipliers \param[in] psir - right multiplies \param[in] epsilon - splitting tolerance \param[in] opts - approximation options \return na - a new approximation ***************************************************************/ struct FunctionTrain * dmrg_sweep_rl(struct FunctionTrain * z, void (*f)(char,size_t,size_t,double *,struct Qmarray **,void *), void * args, struct QR ** phil, struct QR ** psir, double epsilon, struct MultiApproxOpts * opts) { double * RL = NULL; size_t dim = z->dim; struct FunctionTrain * na = function_train_alloc(dim); na->ranks[0] = 1; na->ranks[na->dim] = 1; struct OneApproxOpts * o = NULL; if (psir[dim-2] == NULL){ struct Qmarray * temp0 = NULL; f('R',dim-1,1,NULL,&temp0,args); //qmarray_kron(a->cores[dim-1],b->cores[dim-1]); o = multi_approx_opts_get_aopts(opts,dim-1); psir[dim-2] = qr_reduced(temp0,0,o); qmarray_free(temp0); temp0 = NULL; } size_t nrows = phil[dim-2]->mr; size_t nmult = phil[dim-2]->mc; size_t ncols = psir[dim-2]->mc; RL = calloc_double(nrows * ncols); cblas_dgemm(CblasColMajor,CblasNoTrans,CblasNoTrans,nrows,ncols, nmult,1.0,phil[dim-2]->mat,nrows,psir[dim-2]->mat,nmult,0.0,RL,nrows); double * u = NULL; double * vt = NULL; double * s = NULL; /* printf("Right-Left sweep\n"); */ /* printf("(nrows,ncols)=(%zu,%zu), epsilon=%G\n",nrows,ncols,epsilon); */ size_t rank = truncated_svd(nrows,ncols,nrows,RL,&u,&s,&vt,epsilon); /* printf("rank=%zu\n",rank); */ na->ranks[dim-1] = rank; na->cores[dim-1] = mqma(vt,psir[dim-2]->Q,rank); int ii; for (ii = dim-3; ii > -1; ii--){ double * newpsi = calloc_double( psir[ii+1]->mr * rank); // cblas_dgemm(CblasColMajor,CblasNoTrans,CblasTrans, psir[ii+1]->mr,rank, psir[ii+1]->mc, 1.0,psir[ii+1]->mat,psir[ii+1]->mr,vt,rank, 0.0,newpsi,psir[ii+1]->mr); struct Qmarray * temp = NULL; // qmarray_kron_mat(rank,newpsi,a->cores[ii+1],b->cores[ii+1]); f('R',(size_t)ii+1,rank,newpsi,&temp,args); qr_free(psir[ii]); psir[ii] = NULL; o = multi_approx_opts_get_aopts(opts,(size_t)ii+1); psir[ii] = qr_reduced(temp,0,o); free(RL); RL = NULL; free(newpsi); newpsi = NULL; free(u); u = NULL; free(vt); vt = NULL; free(s); s = NULL; qmarray_free(temp); temp = NULL; nrows = phil[ii]->mr; nmult = phil[ii]->mc; ncols = psir[ii]->mc; RL = calloc_double(nrows * ncols); cblas_dgemm(CblasColMajor,CblasNoTrans,CblasNoTrans,nrows,ncols, nmult,1.0,phil[ii]->mat,nrows,psir[ii]->mat,nmult,0.0,RL,nrows); /* printf("(nrows,ncols)=(%zu,%zu), epsilon=%G\n",nrows,ncols,epsilon); */ rank = truncated_svd(nrows,ncols,nrows,RL,&u,&s,&vt,epsilon); /* printf("rank=%zu\n",rank); */ na->ranks[ii+1] = rank; na->cores[ii+1] = mqma(vt,psir[ii]->Q,rank); } size_t kk,jj; for (jj = 0; jj < rank; jj++){ for (kk = 0; kk < nrows; kk++){ u[jj*nrows+kk] = u[jj*nrows+kk]*s[jj]; } } na->cores[0] = qmam(phil[0]->Q,u,rank); /* exit(1); */ free(RL); RL = NULL; free(u); u = NULL; free(vt); vt = NULL; free(s); s = NULL; return na; }
/***********************************************************//** Perform a left-right dmrg sweep \param[in] z - initial guess \param[in] f - specialized function to multiply core by matrix \param[in] args - arguments to f \param[in,out] phil - left multipliers \param[in] psir - right multiplies \param[in] epsilon - splitting tolerance \param[in] opts - approximation options \return na - a new approximation ***************************************************************/ struct FunctionTrain * dmrg_sweep_lr(struct FunctionTrain * z, void (*f)(char,size_t,size_t, double *, struct Qmarray **, void *), void * args, struct QR ** phil, struct QR ** psir, double epsilon, struct MultiApproxOpts * opts) { double * RL = NULL; size_t dim = z->dim; struct FunctionTrain * na = function_train_alloc(dim); struct OneApproxOpts * o = NULL; na->ranks[0] = 1; na->ranks[na->dim] = 1; if (phil[0] == NULL){ struct Qmarray * temp0 = NULL; f('L',0,1,NULL,&temp0,args); /* printf("temp0 size(%zu,%zu) \n",temp0->nrows,temp0->ncols); */ o = multi_approx_opts_get_aopts(opts,0); phil[0] = qr_reduced(temp0,1,o); qmarray_free(temp0); temp0 = NULL; } /* exit(1); */ size_t nrows = phil[0]->mr; size_t nmult = phil[0]->mc; size_t ncols = psir[0]->mc; RL = calloc_double(nrows * ncols); cblas_dgemm(CblasColMajor,CblasNoTrans,CblasNoTrans,nrows,ncols, nmult,1.0,phil[0]->mat,nrows,psir[0]->mat,nmult,0.0,RL,nrows); double * u = NULL; double * vt = NULL; double * s = NULL; /* printf("Left-Right sweep\n"); */ /* printf("(nrows,ncols)=(%zu,%zu), epsilon=%G\n",nrows,ncols,epsilon); */ size_t rank = truncated_svd(nrows,ncols,nrows,RL,&u,&s,&vt,epsilon); /* printf("rank=%zu\n",rank); */ na->ranks[1] = rank; na->cores[0] = qmam(phil[0]->Q,u,rank); size_t ii; for (ii = 1; ii < dim-1; ii++){ /* printf("ii = %zu\n",ii); */ double * newphi = calloc_double(rank * phil[ii-1]->mc); cblas_dgemm(CblasColMajor,CblasTrans,CblasNoTrans,rank,nmult, nrows,1.0,u,nrows,phil[ii-1]->mat,nrows,0.0,newphi,rank); //struct Qmarray * temp = mqma(newphi,y->cores[ii],rank); //struct Qmarray * temp = qmarray_mat_kron(rank,newphi,a->cores[ii],b->cores[ii]); struct Qmarray * temp = NULL; f('L',ii,rank,newphi,&temp,args); qr_free(phil[ii]); phil[ii] = NULL; o = multi_approx_opts_get_aopts(opts,ii); phil[ii] = qr_reduced(temp,1,o); free(RL); RL = NULL; free(newphi); newphi = NULL; free(u); u = NULL; free(vt); vt = NULL; free(s); s = NULL; qmarray_free(temp); temp = NULL; nrows = phil[ii]->mr; nmult = phil[ii]->mc; ncols = psir[ii]->mc; RL = calloc_double(nrows * ncols); cblas_dgemm(CblasColMajor,CblasNoTrans,CblasNoTrans,nrows,ncols, nmult,1.0,phil[ii]->mat,nrows,psir[ii]->mat,nmult,0.0,RL,nrows); /* printf("(nrows,ncols)=(%zu,%zu), epsilon=%G\n",nrows,ncols,epsilon); */ rank = truncated_svd(nrows,ncols,nrows,RL,&u,&s,&vt,epsilon); /* dprint(nrows,s); */ /* printf("rank=%zu\n",rank); */ na->ranks[ii+1] = rank; na->cores[ii] = qmam(phil[ii]->Q,u,rank); } /* exit(1); */ size_t kk,jj; for (kk = 0; kk < ncols; kk++){ for (jj = 0; jj < rank; jj++){ vt[kk*rank+jj] = vt[kk*rank+jj]*s[jj]; } } na->cores[dim-1] = mqma(vt,psir[dim-2]->Q,rank); free(RL); RL = NULL; free(u); u = NULL; free(vt); vt = NULL; free(s); s = NULL; return na; }