#include "mmclib.h" #include "getvalue.h" #include "parse.h" #include "lstsqr.h" typedef int *pint; typedef int **ppint; typedef Real *pReal; typedef Real **ppReal; typedef Real ***pppReal; typedef Complex *pComplex; MultiMonteCarlo::MultiMonteCarlo(const Structure &_lattice, const Array > &_site_type_list, const iVector3d &_supercell, const SpaceGroup &space_group, const LinkedList &cluster_list, const Array > > &_corrfunc) : lattice(_lattice), site_type_list(_site_type_list), supercell(_supercell), corrfunc(_corrfunc), cur_rho(), cur_conc(), mu(), allowed_flip_site(),allowed_flip_before(),allowed_flip_after(), flip_span(-1,-1,-1) { Real max_clus_len=0.; { LinkedListIterator c(cluster_list); for ( ; c; c++) { Real l=get_cluster_length(c->clus); if (l>max_clus_len) max_clus_len=l; } } margin=find_sphere_bounding_box(lattice.cell,max_clus_len); iVector3d supercell_orig=supercell; for (int mult=1; 1 ; mult++) { supercell=mult*supercell_orig; int i; for (i=0; i<3; i++) { if (supercell(i) < margin(i)) break; } if (i==3) break; } total_box=supercell+2*margin; int spin_total_size=total_box(0)*total_box(1)*total_box(2)*lattice.atom_pos.get_size(); spin=new SPIN_TYPE[spin_total_size]; for (int i=0; i frozen_site(site_in_cell); zero_array(&frozen_site); active_site_in_cell=site_in_cell; if (file_exists("frozensite.in")) { ifstream file("frozensite.in"); while (skip_delim(file)) { int s=-1; file >> s; if (!frozen_site(s)) {active_site_in_cell--;} frozen_site(s)=1; } } which_site=new int[active_site_in_cell]; int s=0; for (int i=0; i c(cluster_list); for (int i=0; c; c++,i++) { rcluster_mult_per_atom[i]=calc_multiplicity(*c,lattice.cell,space_group.point_op,space_group.trans)/(Real)lattice.atom_pos.get_size(); } } E_ref=0.; which_is_empty=-1; nb_point=0; { LinkedListIterator c(cluster_list); int cluster_index=0; for (; c; c++, cluster_index++) { if (c->clus.get_size()==0) {which_is_empty=cluster_index;} if (c->clus.get_size()==1) {nb_point++;} } which_is_point=new int[nb_point]; point_mult=new Real[nb_point]; c.init(cluster_list); cluster_index=0; int point_index=0; for (; c; c++, cluster_index++) { if (c->clus.get_size()==1) { which_is_point[point_index]=cluster_index; point_mult[point_index]=rcluster_mult_per_atom[cluster_index]; point_index++; } } } cur_conc.resize(nb_point); mu.resize(nb_point); zero_array(&mu); pmu=mu.get_buf(); rMatrix3d inv_cell=!lattice.cell; for (int s=0; s long_cluster_list; LinkedList long_cluster_i_list; LinkedListIterator c(cluster_list); int cluster_index=0; for ( ; c; c++,cluster_index++) { if (c->clus.get_size()!=0) { Array clusters; find_equivalent_clusters(&clusters, *c,space_group.cell,space_group.point_op,space_group.trans); for (int ec=0; ecclus(0)=clusters(ec).clus(center_atom)+lat_shift; to_add->site_type(0)=clusters(ec).site_type(center_atom); to_add->func(0)=clusters(ec).func(center_atom); int j=1; for (int i=0; iclus(j)=clusters(ec).clus(i)+lat_shift; to_add->site_type(j)=clusters(ec).site_type(i); to_add->func(j)=clusters(ec).func(i); j++; } } long_cluster_list << to_add; long_cluster_i_list << new int(cluster_index); } } } } } nb_clusters[s]=long_cluster_list.get_size(); cluster_size[s]=new int[nb_clusters[s]]; eci[s]=new Real[nb_clusters[s]]; which_cluster[s]=new int[nb_clusters[s]]; site_offset[s]=new pint[nb_clusters[s]]; spin_val_clus[s]=new ppReal[nb_clusters[s]]; c.init(long_cluster_list); LinkedListIterator c_i(long_cluster_i_list); for (int ic=0; icclus.get_size(); eci[s][ic]=0.; which_cluster[s][ic]=*c_i; site_offset[s][ic]=new int[c->clus.get_size()]; spin_val_clus[s][ic]=new pReal[c->clus.get_size()]; for (int j=0; jclus.get_size(); j++) { int offset_in_cell=which_atom(lattice.atom_pos,c->clus(j),inv_cell); iVector3d offset_cell=to_int(inv_cell*(c->clus(j)-lattice.atom_pos(offset_in_cell))); site_offset[s][ic][j]=((offset_cell(0)*total_box(1) + offset_cell(1))*total_box(2) + offset_cell(2))*site_in_cell + offset_in_cell - s; spin_val_clus[s][ic][j]=new Real[nb_spin_val[offset_in_cell]]; for (int l=0; lsite_type(j))(c->func(j))(l); } } } } } MultiMonteCarlo::~MultiMonteCarlo(void) { for (int s=0; s *pcorr, int site, int type) { Array allcorr(total_clusters); zero_array(&allcorr); for (int c=0; c *pcorr, const Array &sites,const Array &types) { pcorr->resize(nb_point); zero_array(pcorr); for (int i=0; i &corr_constraints, const iVector3d &_flip_span, int min_nb_flip) { flip_span=_flip_span; int withinonecell=0; if (flip_span(0)==0 && flip_span(1)==0 && flip_span(2)==0) {withinonecell=1;} LinkedList > site_list; LinkedList > before_flip_list; LinkedList > > after_flip_list; Array site_done(site_in_cell); zero_array(&site_done); int nb_site_done=0; int nb_in_basis=0; Array > corr_basis; int nbflip=1; while (1) { Array maxsite(nbflip); for (int i=0; i > rawsites(maxsite); for ( ; rawsites; rawsites++) { Array sites(maxsite.get_size()); for (int i=0; i &)rawsites)(i)]; } Array maxtype(maxsite.get_size()); for (int i=0; i &)sites)(i)];} MultiDimIterator > before_types(maxtype); int nb_tries=1; for (int i=0; i before_flip(nb_tries); for (int i=0; i > after_flip; for (; before_types; before_types++) { Array before_corr; calc_delta_point_corr(&before_corr, (const Array &)sites,(const Array &)before_types); MultiDimIterator > after_types(maxtype); for (; after_types; after_types++) { int same; for (same=0; same &)before_types)(same)==((Array &)after_types)(same)) break; } if (same==nbflip) { Array after_corr; calc_delta_point_corr(&after_corr, (const Array &)sites,(const Array &)after_types); Array delta_corr; diff(&delta_corr,after_corr,before_corr); Array c; if (corr_constraints.get_size()(1)!=delta_corr.get_size()) { ERRORQUIT("Incorrect number of point correlations to use the hybrid grandcanonical/canonical mode.\nPlease make sure clusters.out includes all point correlations"); } product(&c,corr_constraints,delta_corr); if (inner_product(c,c) &)before_types)(i);} before_flip(index)=nb_flip; after_flip << new Array(after_types); nb_flip++; if (min_nb_flip==0) { for (int l=0; l<((Array &)sites).get_size(); l++) { cerr << ((Array &)sites)(l) << ": " << ((Array &)before_types)(l) << "->" << ((Array &)after_types)(l) << endl; } cerr << endl; } build_basis(&corr_basis,&nb_in_basis,delta_corr); } } } } if (nb_flip>0) { for (int i=0; i<((Array &)sites).get_size(); i++) { if (site_done(((Array &)sites)(i))==0) { site_done(((Array &)sites)(i))=1; nb_site_done++; } } int addit=1; if (withinonecell) { for (int i=0; i(sites); before_flip_list << new Array(before_flip); Array > *pafter_flip_array=new Array >(); LinkedList_to_Array(pafter_flip_array,after_flip); after_flip_list << pafter_flip_array; } else { cerr << "Ignored" << endl; } } } if (nb_in_basis >= nb_point-corr_constraints.get_size()(0) && (nb_site_done==active_site_in_cell) && nbflip>=min_nb_flip) break; nbflip++; } LinkedList_to_Array(&allowed_flip_site,site_list); LinkedList_to_Array(&allowed_flip_before,before_flip_list); LinkedList_to_Array(&allowed_flip_after,after_flip_list); } int MultiMonteCarlo::force_spin_flip(int *cell, int incell, int newspin) { int i; int mcell[3],mcellscan[3],offset; int oldspin; Real denergy,dconc; int cluster_count,site_count; int **pcluster; Real ***pppspin_val_clus,**ppspin_val_clus; int *pwhich_cluster; int *poffset,*psize; Real *peci, *prho, *prho2, *prcluster_mult_per_atom; Real rho; for (i=0; i<3; i++) { mcell[i]=cell[i]+margin(i); } offset=((mcell[0]*total_box(1) + mcell[1])*total_box(2) + mcell[2])*site_in_cell + incell; oldspin=spin[offset]; denergy=0.; for (i=total_clusters, prho=new_rho; i>0; i--, prho++) { *prho=0.; } for (cluster_count=nb_clusters[incell], pcluster=site_offset[incell], pppspin_val_clus=spin_val_clus[incell], psize=cluster_size[incell], pwhich_cluster=which_cluster[incell], peci=eci[incell]; cluster_count>0; cluster_count--, pcluster++, pppspin_val_clus++, psize++, pwhich_cluster++, peci++) { poffset=*pcluster; ppspin_val_clus=*pppspin_val_clus; rho=(*ppspin_val_clus)[newspin]-(*ppspin_val_clus)[oldspin]; poffset++; ppspin_val_clus++; for (site_count=(*psize)-1; site_count>0; site_count--, poffset++, ppspin_val_clus++) { rho*=(*ppspin_val_clus)[spin[offset+(*poffset)]]; } new_rho[*pwhich_cluster]+=rho; denergy+=(*peci)*rho; } for (i=0; i=supercell(i)) {mcell[i]-=supercell(i);} } for (mcellscan[0]=mcell[0]; mcellscan[0]cur_energy=cur_energy; pstate->cur_disorder_param=cur_disorder_param; pstate->cur_rho.resize(total_clusters); for (int i=0; icur_rho(i)=pcur_rho[i];} pstate->saved_spins.delete_all(); } void MultiMonteCarlo::save_spin(MultiMonteCarloState *pstate, int *cell, int incell) { FlipInfo *pinfo=new FlipInfo(); for (int i=0; i<3; i++) { pinfo->cell[i]=cell[i]+margin(i); } pinfo->incell=incell; int offset=((pinfo->cell[0]*total_box(1) + pinfo->cell[1])*total_box(2) + pinfo->cell[2])*site_in_cell + incell; pinfo->spin=spin[offset]; pstate->saved_spins << pinfo; } void MultiMonteCarlo::restore_state(const MultiMonteCarloState &state) { cur_energy=state.cur_energy; cur_disorder_param=state.cur_disorder_param; for (int i=0; i it(state.saved_spins); for ( ; it; it++) { int mcell[3]; for (int i=0; i<3; i++) { mcell[i]=it->cell[i]; if (mcell[i]>=supercell(i)) {mcell[i]-=supercell(i);} } int mcellscan[3]; for (mcellscan[0]=mcell[0]; mcellscan[0]incell]=it->spin; } } } } } int MultiMonteCarlo::access(int *cell, int incell) { int mcell[3]; for (int i=0; i<3; i++) { mcell[i]=cell[i]+margin(i); } int offset=((mcell[0]*total_box(1) + mcell[1])*total_box(2) + mcell[2])*site_in_cell + incell; return spin[offset]; } void MultiMonteCarlo::multi_spin_flip(void) { int which_flip,before_index,after_index; Array cells; Array oldspin; do { which_flip=random(allowed_flip_site.get_size()); cells.resize(allowed_flip_site(which_flip).get_size()); iVector3d center; if (flip_span(0)>=0) { for (int j=0; j<3; j++) { center(j)=random(supercell(j)); } } for (int i=0; i=0) { cells(i)(j)=(supercell(j)+center(j)+random(2*flip_span(j)+1)-flip_span(j)) % supercell(j); } else { cells(i)(j)=random(supercell(j)); } } for (ii=0; ii---" << endl; } void MultiMonteCarlo::set_eci(const Array &new_eci) { if (which_is_empty>=0) { E_ref=new_eci(which_is_empty)/lattice.atom_pos.get_size(); } else { E_ref=0.; } for (int s=0; s > &conc) { Array > sconc; sconc=conc; for (int i=0; i bb(iVector3d(0,0,0),total_box-iVector3d(1,1,1)); MultiDimIterator cell(supercell); for ( ; cell; cell++) { for (int offset_in_cell=0; offset_in_cell image(iVector3d(-1,-1,-1),iVector3d(1,1,1)); for ( ; image; image++) { iVector3d image_cell=(iVector3d &)cell+msupercell*(iVector3d &)image+margin; if (bb.is_in(image_cell)) { int offset=((image_cell(0)*total_box(1) + image_cell(1))*total_box(2) + image_cell(2))*site_in_cell + offset_in_cell; spin[offset]=the_spin; } } } } int spin_size=supercell(0)*supercell(1)*supercell(2)*site_in_cell; for (int i=0; i bb(iVector3d(0,0,0),total_box-iVector3d(1,1,1)); for (int at=0; at image(iVector3d(-1,-1,-1),iVector3d(1,1,1)); for ( ; image; image++) { iVector3d image_cell=cell+msupercell*(iVector3d &)image+margin; if (bb.is_in(image_cell)) { int offset=((image_cell(0)*total_box(1) + image_cell(1))*total_box(2) + image_cell(2))*site_in_cell + s; spin[offset]=newspin; } } int offset=((cell(0)*supercell(1) + cell(1))*supercell(2) + cell(2))*site_in_cell + s; spin_orig[offset]=newspin; } } else { rMatrix3d inv_cell=!str.cell; iMatrix3d msupercell; msupercell.diag(supercell); BoundingBox bb(iVector3d(0,0,0),total_box-iVector3d(1,1,1)); MultiDimIterator cell(supercell); int quickload=0; if (file_exists("quickload")) {quickload=1;} cerr << "quickload=" << quickload << endl;; int at=-1; for (; cell; cell++) { rVector3d rcell=lattice.cell*to_real((iVector3d &)cell); for (int s=0; s image(iVector3d(-1,-1,-1),iVector3d(1,1,1)); for ( ; image; image++) { iVector3d image_cell=(iVector3d &)cell+msupercell*(iVector3d &)image+margin; if (bb.is_in(image_cell)) { int offset=((image_cell(0)*total_box(1) + image_cell(1))*total_box(2) + image_cell(2))*site_in_cell + s; spin[offset]=newspin; } } iVector3d thecell=(iVector3d &)cell; int offset=((thecell(0)*supercell(1) + thecell(1))*supercell(2) + thecell(2))*site_in_cell + s; spin_orig[offset]=newspin; } } } cerr << "end init" << endl; calc_from_scratch(); extension_calc_from_scratch(); cerr << "end calc" << endl; } void MultiMonteCarlo::calc_from_scratch(void) { cur_disorder_param=0.; cur_energy=0; for (int i=0; i cur_cell(supercell); for ( ; cur_cell; cur_cell++) { iVector3d m_cur_cell=(iVector3d &)cur_cell+margin; for (int s=0; s=0) {cur_rho(which_is_empty)=1.;} for (int i=0; i & MultiMonteCarlo::get_cur_concentration(void) { for (int i=0; i &_mu) { T=_T; for (int i=0; i0; i--, prho++) { *prho=0.; } for (cluster_count=nb_clusters[incell], pcluster=site_offset[incell], pppspin_val_clus=spin_val_clus[incell], psize=cluster_size[incell], pwhich_cluster=which_cluster[incell], peci=eci[incell]; cluster_count>0; cluster_count--, pcluster++, pppspin_val_clus++, psize++, pwhich_cluster++, peci++) { poffset=*pcluster; ppspin_val_clus=*pppspin_val_clus; rho=(*ppspin_val_clus)[newspin]-(*ppspin_val_clus)[oldspin]; poffset++; ppspin_val_clus++; for (site_count=(*psize)-1; site_count>0; site_count--, poffset++, ppspin_val_clus++) { rho*=(*ppspin_val_clus)[spin[offset+(*poffset)]]; } new_rho[*pwhich_cluster]+=rho; denergy+=(*peci)*rho; } for (i=0; i=supercell(i)) {mcell[i]-=supercell(i);} } for (mcellscan[0]=mcell[0]; mcellscan[0] &labellookup, const Array &atom_label, ofstream &file, const rMatrix3d &axes) { for (int i=0; i<3; i++) { file << axes.get_column(i) << endl; } for (int i=0; i<3; i++) { file << (!axes)*((Real)(supercell(i))*lattice.cell.get_column(i)) << endl; } rMatrix3d iaxes=!axes; MultiDimIterator cur_cell(supercell); for ( ; cur_cell; cur_cell++) { iVector3d m_cur_cell=(iVector3d &)cur_cell+margin; for (int s=0; s *pdata) { pdata->resize(2+nb_point+total_clusters); (*pdata)(0)=get_cur_energy(); (*pdata)(1)=get_cur_disorder_param(); int i=2; Array conc; conc=get_cur_concentration(); for (int j=0; j rho; rho=get_cur_corr(); for (int j=0; j data; pmc->get_thermo_data(&data); while (accum->new_data(data)) { pmc->run(1,mode); pmc->get_thermo_data(&data); } } #include "anyfft.h" KSpaceMultiMonteCarlo::KSpaceMultiMonteCarlo(const Structure &_lattice, const Array > &_site_type_list, const iVector3d &_supercell, const SpaceGroup &space_group, const LinkedList &cluster_list, const Array > > &_corrfunc, KSpaceECI *_p_kspace_eci): MultiMonteCarlo(_lattice,_site_type_list,_supercell,space_group,cluster_list,_corrfunc), flipped_spins(), ft_spin(), ft_eci(), dir_eci(), convol(), ref_x() { p_kspace_eci=_p_kspace_eci; nsite=_lattice.atom_pos.get_size(); size=supercell(0)*supercell(1)*supercell(2); rsize=(Real)size; ft_spin.resize(nsite); for (int s=0; s a) { { ofstream file("tmp.gnu"); file << "set hidden" << endl << "splot 'tmp.out' u 1:2:3 w l" << endl << "pause -1" << endl; } { ofstream file("tmp.out"); for (int z=0; zget_k_space_eci(&ft_eci, ref_x); dir_eci=ft_eci; for (int s=0; s0.) { //cerr << cur_recip_E << endl; //} } } } //cerr << "end" << endl; for (int s=0; s diffx; diff(&diffx,get_cur_concentration(),ref_x); //cerr << "forget" << endl; if (max_norm(diffx)>threshold_dx) { extension_calc_from_scratch(); } else { if (flip_time>0) { //cerr << "time: " << nbflip << " " << flip_time << " " << 2*fft_time/flip_time << endl; if (nbflip > 2*fft_time/flip_time) { //cerr << "before= " << extension_get_energy() << endl; extension_calc_from_scratch(); //cerr << "after= " << extension_get_energy() << endl; } } } } void KSpaceMultiMonteCarlo::extension_update_spin_flip(int *cell, int incell, int oldspin, int newspin) { flip_time=clock(); int dr[3]; int mdr[3]; int *psupercell=supercell.get_buf(); Array rspinchange(nb_spin_val[incell]); rspinchange(0)=0.; for (int ss=1; ss i(flipped_spins); for (; i; i++) { for (int j=0; j<3; j++) { dr[j] =(cell[j]-(i->cell[j])+psupercell[j]) % psupercell[j]; mdr[j]=(i->cell[j]-cell[j]+psupercell[j]) % psupercell[j]; } //int offsetdr=((dr[0]*psupercell[1] + dr[1])*psupercell[2] + dr[2]); //permbug int offsetdr =((dr[2]*psupercell[1] + dr[1])*psupercell[0] + dr[0]); int offsetmdr=((mdr[2]*psupercell[1] + mdr[1])*psupercell[0] + mdr[0]); for (int ss=1; ssincell]; tt++) { if (incell>=i->incell) { dE+=2.*real(dir_eci(incell)(i->incell)(ss)(tt)(offsetdr)*rspinchange(ss)*i->dspin(tt)); } else { dE+=2.*real(dir_eci(i->incell)(incell)(tt)(ss)(offsetmdr)*rspinchange(ss)*i->dspin(tt)); } } } } cur_recip_E+=dE/(rspin_size); /* cerr << "Eafterflip=" << cur_recip_E << endl; int ck=0; if (ck==1) { extension_calc_from_scratch(); cerr << cur_recip_E << endl; } */ flipped_spins.push_front(new FlippedSpin(cell,incell,rspinchange)); flip_time=clock()-flip_time; } void KSpaceMultiMonteCarlo::extension_undo_spin_flip(void) { LinkedListIterator flip(flipped_spins); while ((FlippedSpin *)flip != psave_spins) { delete flipped_spins.detach(flip); } cur_recip_E=save_recip_E; psave_spins=NULL; //cerr << "undo" << flipped_spins.get_size() << endl; } KSpaceMultiMonteCarlo::~KSpaceMultiMonteCarlo() { // free all dynamically allocated memory; }