#ifdef USE_QIO #include #include #include #include #define PROFILE CPS_START_NAMESPACE using namespace std; // qio-factory functions // global variable for fanctor (could make a separated record and read from it, but then we would need if statement...) struct qio_genfield_glb_type { int precision; int n_fields; int f_size_per_site; int n_sites; }; static qio_genfield_glb_type qio_genfield_glb; void qio_genfield_get_glb(char *buf_, size_t site_index, int count, void *arg_) { moveMem(buf_, arg_, sizeof(qio_genfield_glb_type)) ; qio_genfield_glb_type* a= &qio_genfield_glb; #if 1 VRB.Result("","qio_genfield_get_glb", "writing %d %d %d %d\n", a-> precision, a-> n_fields, a-> f_size_per_site, a-> n_sites ); #endif // int *arg=(int*)arg_; int *buf=(int*)buf_; // buf[0]=arg[0]; buf[1]=arg[1]; } void qio_getGenField(char *buf_, size_t site_index, int count, void *arg) { /*printf(" called with count %i\n",count);*/\ const int n_field = qio_genfield_glb. n_fields; const size_t f_size = qio_genfield_glb. f_size_per_site; const int n_sites = qio_genfield_glb. n_sites; #if 0 VRB.Result("","qio_geGenField", "%d %d %d %d %d %x\n", n_field, f_size, n_sites,count, site_index, buf_); #endif /* The field should store data in memory in the following format : [ 1 st field ] [ 2 nd field ] ... [ (n_fields-1q)-th field ] where [ n-th field ] is [ f_size_per_site Floats for (0,0,0,0) ] [ f_size_per_site Floats for (1,0,0,0) ] [ f_size_per_site Floats for (2,0,0,0) ] .... [f_size_per_site Floats for (Nx-1, Ny-1, Nz-1, Nt-1) ] To save the number of io, we rearrange the file format as follows : [ n_fields* f_size_per_site Floats for (0,0,0,0) ] [ n_fields* f_size_per_site Floats for (1,0,0,0) ] [ n_fields* f_size_per_site Floats for (2,0,0,0) ] .... [n_fields* f_size_per_site Floats for (Nx-1, Ny-1, Nz-1, Nt-1) ] the most fastest changing index is the f_size_per_site degree in one field, then the index for the field, 0 ... n_field-1 This rearrangement requires the non-local memory access, but I hope the benefit of n_field times smaller number of I/O will supersede the slow down. */ if(qio_genfield_glb.precision){ const Float *field = (Float*) arg; Float *buf = (Float*) buf_; for(int field_i=0; field_i QIO_INFO_STRING_MAX){ ERR.General(cname,fname," xml_info_file too large: %i\n %s\n", (strlen(xml_info_field)*sizeof(char)), xml_info_field); exit(-12); } QIO_String *qio_file_header = QIO_string_create(); QIO_string_set( qio_file_header, xml_info_field ); qio_openOutput(outfile, qio_file_header, volFormat); // Fist , store the n_fields and f_size_per_site information as global data QIO_String *no_string = QIO_string_create(); QIO_string_set( no_string, ""); QIO_RecordInfo* glb_rec_info = QIO_create_record_info(QIO_GLOBAL, NULL, NULL, 0, (char*)"", (char*)"I", 0, 0, sizeof(qio_genfield_glb_type), 1); qio_genfield_glb.n_fields = n_fields; qio_genfield_glb. f_size_per_site = f_size_per_site; // To the file, we record the number of global sites qio_genfield_glb. n_sites = GJP. VolSites(); return_val += QIO_write( qio_Output, glb_rec_info, no_string, qio_genfield_get_glb, sizeof(qio_genfield_glb_type), sizeof(int), (void*) &qio_genfield_glb); // For the actual I/O, we use the number of local sites qio_genfield_glb. n_sites = GJP. VolNodeSites(); // Now create the record info for field itself // printf("record :%d %d = %d\n", n_fields, f_size_per_site, n_fields * f_size_per_site); QIO_RecordInfo *record_field ; // Do the actual work if(SingleDouble) { //output in double-precision record_field = QIO_create_record_info(QIO_FIELD, NULL, NULL, 0, (char*)"GenericField", (char*)"D", 0, 0, n_fields * f_size_per_site*sizeof(Float), 1); // color=0 (not used), spin=0 (not used), sizepersite, there will be num_fields return_val += QIO_write( qio_Output, record_field, no_string, qio_getGenField, n_fields* f_size_per_site*sizeof(Float), sizeof(Float), field); } else { //ERR.NotImplemented(cname,fname,"Sorry for lack of support for single precision sotre at this moment"); //output in single-precision record_field = QIO_create_record_info(QIO_FIELD, NULL, NULL, 0, (char*)"GenericField", (char*)"F", 0, 0, n_fields * f_size_per_site*sizeof(float), 1); // color=0 (not used), spin=0 (not used), sizepersite, there will be num_fields return_val += QIO_write( qio_Output, record_field, no_string, qio_getGenField, n_fields* f_size_per_site*sizeof(float), sizeof(float), field); } if ( (return_val == 0) ) VRB.Result(cname,fname,"QIO_write successfull...\n"); else ERR.General(cname,fname,"ERROR QIO: QIO_write(s) returned %i\n",return_val); // clean-up QIO_destroy_record_info( glb_rec_info ); QIO_destroy_record_info(record_field); QIO_string_destroy(qio_file_header); QIO_string_destroy(no_string); qio_closeOutput(); #ifdef PROFILE if(!UniqueID()) printf("%s %g sec\n",cname,time_elapse()); #endif VRB.FuncEnd(cname,fname); } void qio_writeGenericFields::setHeader(const char * ensemble_id, const char * ensemble_label, const int traj, const char * field_type_label) { const char * fname = "setHeader(...)"; VRB.Func(cname,fname); if(strlen(ensemble_id) > MAX_HEADER_LINE) { ERR.General(cname,fname,"ERROR: length of ensemble_id exceeds maximum length!\n"); exit(-1); } else strcpy(header_ensemble_id, ensemble_id); if(strlen(ensemble_label) > MAX_HEADER_LINE) { ERR.General(cname,fname,"ERROR: length of ensemble_label exceeds maximum length!\n"); exit(-1); } else strcpy(header_ensemble_label, ensemble_label); header_traj = traj; if(strlen(field_type_label) > MAX_HEADER_LINE) { ERR.General(cname,fname,"ERROR: length of field_type_label exceeds maximum length!\n"); exit(-1); } else strcpy(header_field_type_label, field_type_label); VRB.FuncEnd(cname,fname); } CPS_END_NAMESPACE #endif