00001
00002
00003
00004
00005
00006
00007
00008 #include "algebra_interface.h"
00009 #include "calculation_options.h"
00010 #include "blas.h"
00011 #include "moinfo.h"
00012 #include "memory_manager.h"
00013 #include "utilities.h"
00014 #include "error.h"
00015 #include <limits>
00016 #include <cmath>
00017
00018 #include <libpsio/psio.h>
00019 #include <libciomr/libciomr.h>
00020 #include <libqt/qt.h>
00021
00022 extern FILE *infile, *outfile;
00023
00024 namespace psi{ namespace psimrcc{
00025
00026 using namespace std;
00027
00028 vector<pair<string,string> > diis_matrices;
00029 const double diis_singular_tollerance = 1.0e-12;
00030
00031 void CCBLAS::diis_add(string amps, string delta_amps)
00032 {
00033 vector<string> amps_names = moinfo->get_matrix_names(amps);
00034 vector<string> delta_amps_names = moinfo->get_matrix_names(delta_amps);
00035 for(int n=0;n<amps_names.size();n++){
00036 diis_matrices.push_back(make_pair(amps_names[n],delta_amps_names[n]));
00037 }
00038 }
00039
00040 void CCBLAS::diis_save_t_amps(int cycle)
00041 {
00042 int diis_step = cycle % options->get_int_option("MAXDIIS");
00043 for(vector<pair<string,string> >::iterator it=diis_matrices.begin();it!=diis_matrices.end();++it){
00044 for(int h=0;h<moinfo->get_nirreps();h++){
00045 CCMatIrTmp Amps = get_MatIrTmp(it->first,h,none);
00046 double** matrix = Amps->get_matrix()[h];
00047 size_t block_sizepi = Amps->get_block_sizepi(h);
00048 if(block_sizepi>0){
00049 char data_label[80];
00050 sprintf(data_label,"%s_%s_%d_%d",(it->first).c_str(),"DIIS",h,diis_step);
00051 psio_write_entry(MRCC_ON_DISK,data_label,(char*)&(matrix[0][0]),block_sizepi*sizeof(double));
00052 }
00053 }
00054 }
00055 }
00056
00057 void CCBLAS::diis(int cycle)
00058 {
00059 int diis_step = cycle % options->get_int_option("MAXDIIS");
00060
00061 for(vector<pair<string,string> >::iterator it=diis_matrices.begin();it!=diis_matrices.end();++it){
00062 if(it->second.find("t3_delta")==string::npos){
00063 for(int h=0;h<moinfo->get_nirreps();h++){
00064 CCMatIrTmp DeltaAmps = get_MatIrTmp(it->second,h,none);
00065 double** matrix = DeltaAmps->get_matrix()[h];
00066 size_t block_sizepi = DeltaAmps->get_block_sizepi(h);
00067 if(block_sizepi>0){
00068 char data_label[80];
00069 sprintf(data_label,"%s_%s_%d_%d",(it->second).c_str(),"DIIS",h,diis_step);
00070 psio_write_entry(MRCC_ON_DISK,data_label,(char*)&(matrix[0][0]),block_sizepi*sizeof(double));
00071 }
00072 }
00073 }
00074 }
00075
00076 fprintf(outfile," S");
00077
00078
00079 if(diis_step==options->get_int_option("MAXDIIS")-1){
00080 double** diis_B;
00081 double* diis_A;
00082 allocate1(double,diis_A,options->get_int_option("MAXDIIS")+1);
00083 allocate2(double,diis_B,options->get_int_option("MAXDIIS")+1,options->get_int_option("MAXDIIS")+1);
00084 bool singularities_found = false;
00085 for(vector<pair<string,string> >::iterator it=diis_matrices.begin();it!=diis_matrices.end();++it){
00086
00087 for(int i=0;i<options->get_int_option("MAXDIIS");i++){
00088 diis_A[i]=0.0;
00089 diis_B[i][options->get_int_option("MAXDIIS")]=diis_B[options->get_int_option("MAXDIIS")][i]=-1.0;
00090 for(int j=0;j<options->get_int_option("MAXDIIS");j++)
00091 diis_B[i][j]=0.0;
00092 }
00093 diis_B[options->get_int_option("MAXDIIS")][options->get_int_option("MAXDIIS")]=0.0;
00094 diis_A[options->get_int_option("MAXDIIS")]=-1.0;
00095
00096
00097 for(int h=0;h<moinfo->get_nirreps();h++){
00098 CCMatIrTmp Amps = get_MatIrTmp(it->first,h,none);
00099 size_t block_sizepi = Amps->get_block_sizepi(h);
00100 if(block_sizepi>0){
00101 double* i_matrix;
00102 double* j_matrix;
00103 allocate1(double,i_matrix,block_sizepi);
00104 allocate1(double,j_matrix,block_sizepi);
00105
00106
00107 for(int i=0;i<options->get_int_option("MAXDIIS");i++){
00108
00109 char i_data_label[80];
00110 sprintf(i_data_label,"%s_%s_%d_%d",(it->second).c_str(),"DIIS",h,i);
00111 psio_read_entry(MRCC_ON_DISK,i_data_label,(char*)&(i_matrix[0]),block_sizepi*sizeof(double));
00112
00113 for(int j=i;j<options->get_int_option("MAXDIIS");j++){
00114
00115 char j_data_label[80];
00116 sprintf(j_data_label,"%s_%s_%d_%d",(it->second).c_str(),"DIIS",h,j);
00117 psio_read_entry(MRCC_ON_DISK,j_data_label,(char*)&(j_matrix[0]),block_sizepi*sizeof(double));
00118
00119 int dx = 1;
00120 int lenght = block_sizepi;
00121 if( block_sizepi < static_cast<size_t>(numeric_limits<int>::max()) ){
00122 diis_B[i][j] += F_DDOT(&lenght,i_matrix,&dx,j_matrix,&dx);
00123 diis_B[j][i] = diis_B[i][j];
00124 }else{
00125 print_error("The numeric limits for int was reached for F_DDOT",__FILE__,__LINE__);
00126 }
00127 }
00128 }
00129 release1(i_matrix);
00130 release1(j_matrix);
00131 }
00132 }
00133
00134
00135 int matrix_size = options->get_int_option("MAXDIIS") + 1;
00136 int* IPIV = new int[matrix_size];
00137 int nrhs = 1;
00138 int info = 0;
00139 F_DGESV(&matrix_size, &nrhs, &(diis_B[0][0]),&matrix_size, &(IPIV[0]), &(diis_A[0]),&matrix_size, &info);
00140 delete[] IPIV;
00141
00142
00143 if(!info){
00144 for(int h=0;h<moinfo->get_nirreps();h++){
00145 CCMatIrTmp Amps = get_MatIrTmp(it->first,h,none);
00146 size_t block_sizepi = Amps->get_block_sizepi(h);
00147 if(block_sizepi>0){
00148
00149 double* i_matrix;
00150 double* j_matrix;
00151 allocate1(double,i_matrix,block_sizepi);
00152 allocate1(double,j_matrix,block_sizepi);
00153 double* t_matrix = &(Amps->get_matrix()[h][0][0]);
00154 Amps->zero_matrix_block(h);
00155 for(int i=0;i<options->get_int_option("MAXDIIS");i++){
00156 char i_data_label[80];
00157 sprintf(i_data_label,"%s_%s_%d_%d",(it->first).c_str(),"DIIS",h,i);
00158 psio_read_entry(MRCC_ON_DISK,i_data_label,(char*)&(i_matrix[0]),block_sizepi*sizeof(double));
00159 for(size_t n=0;n<block_sizepi;n++){
00160 t_matrix[n] += diis_A[i]*i_matrix[n];
00161 }
00162 }
00163 release1(i_matrix);
00164 release1(j_matrix);
00165 }
00166 }
00167 }else{
00168 singularities_found = true;
00169 }
00170
00171 }
00172 fprintf(outfile,"/E");
00173 if(singularities_found)
00174 fprintf(outfile," (singularities found)");
00175 release1(diis_A);
00176 release2(diis_B);
00177 }
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 }}