Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions R/readutils.R
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,8 @@ readtextcf <- function(file, Time=48, sym=TRUE, path="", skip=1, check.t=0, ind.
#' '0001/mes_contr_2pts', not the lack of the smearing suffix.
#' @param smear_combs_to_read Character vector containing the smearing cominations that are to be read.
#' These will be attached to the `file_basenames_to_read` in the reading routine.
#' For corrtype = 2pt, the names are added with an underscore,
#' for corrtype = general, the names are added with a slash.
#' @param Time Integer, time extent of the lattice.
#' @param combs_to_read Data frame containing the indices of the masses and r-paramter combinations to
#' be read as well as the name of the spin combination.
Expand All @@ -682,6 +684,12 @@ readtextcf <- function(file, Time=48, sym=TRUE, path="", skip=1, check.t=0, ind.
#' m1_idx \tab m2_idx \tab r1_idx \tab r2_idx \tab spin_comb \cr
#' 1 \tab 2 \tab 0 \tab 0 \tab "P5P5"
#' }
#' In the case of generalized orperator names, the data frame contains the
#' names of the opreator and the name of the spin combination, like this:
#' \tabular{rrrrr}{
#' op1_idx \tab op2_idx \tab spin_comb \cr
#' C_H \tab H_H_S_H \tab "P5P5"
#' }
#' @param sym.vec Integer or numeric vector. Specifies whether the correlator at
#' the given position is symmetric (+1.0) or anti-symmetric (-1.0 )
#' under time reflection. This is passed to \code{symmetrise.cf}. This
Expand All @@ -691,6 +699,10 @@ readtextcf <- function(file, Time=48, sym=TRUE, path="", skip=1, check.t=0, ind.
#' @param symmetrise Boolean, specifies whether averaging over backward and forward
#' correlators should be done after the correlator has been read in.
#' @param nts Integer, number of time slices to be read from the correlator files.
#' @param corrtype Character. Determines the structure of the correlator names that are read.
#' 2pt reads correlators of the form S0_th0_m0_r0_ll ^ \dag S0_th0_m0_r0_ll,
#' general reads any operator name containing underscores, for example
#' C_H ^ \dag and Dth0_A0_C_P_H_H_S_H
#'
#' @return
#' Returns an object of class `cf`.
Expand All @@ -702,12 +714,17 @@ readnissatextcf <- function(file_basenames_to_read,
combs_to_read,
nts = Time,
sym.vec = c(1),
symmetrise = FALSE)
symmetrise = FALSE,
corrtype="2pt")
{
if (corrtype == "2pt") { corrtypenum=1}
else if (corrtype == "general") { corrtypenum=2}
else { stop("invalid correlation type given! must be either 2pt or general") }
tmp <- read_nissa_textcf_kernel(file_basenames_to_read,
smear_combs_to_read,
nts,
combs_to_read)
combs_to_read,
corrtypenum)

total_nts <- nts*length(smear_combs_to_read)*nrow(combs_to_read)

Expand Down
231 changes: 173 additions & 58 deletions src/read_nissa_textcf_kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

using namespace Rcpp;

// corrtypes: what type of information is read from the file
// 1=2pt: m1, m2, r1, r2, spin_info
// 2=newcorr: op1, op2, spin_info

/**
* @brief read 2*nts doubles from a std::ifstream
*
Expand Down Expand Up @@ -52,6 +56,23 @@ inline std::string make_key_2pt(unsigned int m1_idx, unsigned int m2_idx, unsign
return std::string(ckey);
}

/**
* @brief make a key string of two operators
*
* @param op1_idx name of the first correlator, for example C_H
* @param op2_idx name of the second correlator, for example H_H_S_H
* @param spin_comb name of the spin combination, for example "P5P5" or "V1A0"
*
* @return key of the form "op1_%s_op2_%s_%s"
*/
inline std::string make_key_newcorr(std::string op1_idx, std::string op2_idx, std::string spin_comb)
{
char ckey[100];
snprintf(ckey, 100, "op1_%s_op2_%s_%s",
op1_idx.c_str(), op2_idx.c_str(), spin_comb.c_str());
return std::string(ckey);
}

/**
* @brief read correlator meta-data and map to file positions
* @description Nissa text correlator files contain meta-data in the form
Expand All @@ -73,63 +94,129 @@ inline std::string make_key_2pt(unsigned int m1_idx, unsigned int m2_idx, unsign
*
* @param ifs file to be parsed
* @param filemap output, map of file positions for the various correlators in the file
* @param corrtype: what kind of correlator to look for, either 1, with specified m, r, or 2, with any possible string containing an underscore specified
*/
inline void map_file(std::ifstream &ifs, std::map<std::string, std::iostream::pos_type> & filemap){
inline void map_file(std::ifstream &ifs, std::map<std::string, std::iostream::pos_type> & filemap, const size_t corrtype=1){
if( !ifs.good() ){
stop("map_file: input file stream not in a good state!");
}

std::string linebuf;
std::string::size_type comment_pos;

// currently the key for a two-point function consists of four unsigned integers (two mass and two r indices)
// and the name of the spin combination stored in the correlator
// a generalisation of the reader will have to modify this as well as the key construction
// for now we store the numeric key components in this array
unsigned int key_components[4];

while( ifs.good() ){
std::getline(ifs, linebuf);
// we search for commented lines
comment_pos = linebuf.find("#");
if( comment_pos != std::string::npos ){
// in these commented lines, we extract either
// the current set of mass / r parameter combinations
// or the current spin combination
// the line looks like so:
// " # Contraction of S0_th0_m0_r0_ll ^ \dag and S0_th0_m0_r0_ll"
std::string::size_type contr_pos = linebuf.find("Contraction");
if( contr_pos != std::string::npos ){
std::vector<char> lbcopy( linebuf.size() + 1 );
lbcopy[ linebuf.size() ] = '\0';
memcpy( lbcopy.data(), linebuf.c_str(), linebuf.size() );
unsigned int key_components_counter = 0;
char * token = strtok(lbcopy.data(), "_");
while( key_components_counter != 4 || token != NULL ){
if( token[0] == 'm' || token[0] == 'r'){
key_components[key_components_counter] = atoi(token+1);
key_components_counter++;
if(corrtype==1){
// currently the key for a two-point function consists of four unsigned integers (two mass and two r indices)
// and the name of the spin combination stored in the correlator
// a generalisation of the reader will have to modify this as well as the key construction
// for now we store the numeric key components in this array
unsigned int key_components[4];
while( ifs.good() ){
std::getline(ifs, linebuf);
// we search for commented lines
comment_pos = linebuf.find("#");
if( comment_pos != std::string::npos ){
// in these commented lines, we extract either
// the current set of mass / r parameter combinations
// or the current spin combination
// the line looks like so:
// " # Contraction of S0_th0_m0_r0_ll ^ \dag and S0_th0_m0_r0_ll"
std::string::size_type contr_pos = linebuf.find("Contraction");
if( contr_pos != std::string::npos ){
std::vector<char> lbcopy( linebuf.size() + 1 );
lbcopy[ linebuf.size() ] = '\0';
memcpy( lbcopy.data(), linebuf.c_str(), linebuf.size() );
unsigned int key_components_counter = 0;
char * token = strtok(lbcopy.data(), "_");
while( key_components_counter != 4 || token != NULL ){
if( token[0] == 'm' || token[0] == 'r'){
key_components[key_components_counter] = atoi(token+1);
key_components_counter++;
}
token = strtok(NULL, "_");
}
token = strtok(NULL, "_");
}
if(key_components_counter != 4 && token == NULL){
char message[200];
snprintf(message, 200, "map_file: unable to construct key components in parsing of '%s'", linebuf.c_str());
stop(message);
if(key_components_counter != 4 && token == NULL){
char message[200];
snprintf(message, 200, "map_file: unable to construct key components in parsing of '%s'", linebuf.c_str());
stop(message);
}
} else {
// the line looks like so:
// " # P5S0"
std::string::size_type last_space_pos = linebuf.find_last_of(" ");
std::string spin_comb = linebuf.substr(last_space_pos+1);
// now we can build the key
std::string key = make_key_2pt(key_components[0], key_components[2], key_components[1], key_components[3], spin_comb);
// and store the position after the current newline as the starting point
// of the present correlator
filemap[ key ] = ifs.tellg();
}
} else {
} // found commented line
} //while good
} // if corrtype==1
if(corrtype==2){
// currently the key for any correlator is the name of the first and the second correlator,
// and the name of the spin combination stored in the correlator
std::string key_components[2];
while( ifs.good() ){
std::getline(ifs, linebuf);
// we search for commented lines
comment_pos = linebuf.find("#");
if( comment_pos != std::string::npos ){
// in these commented lines, we extract either
// the current operators
// or the current spin combination
// the line looks like so:
// " # P5S0"
std::string::size_type last_space_pos = linebuf.find_last_of(" ");
std::string spin_comb = linebuf.substr(last_space_pos+1);
// now we can build the key
std::string key = make_key_2pt(key_components[0], key_components[2], key_components[1], key_components[3], spin_comb);
// and store the position after the current newline as the starting point
// of the present correlator
filemap[ key ] = ifs.tellg();
}
}
}
// " # Contraction of C_H ^ \dag and Dth0_A0_C_P_H_H_S_H "
std::string::size_type contr_pos = linebuf.find("Contraction");
if( contr_pos != std::string::npos ){
unsigned int key_components_counter = 0;
std::string token;
std::string delimiter (" \0");
size_t pos = linebuf.find_first_of(delimiter, 0);
// The different parts of the string are separated by spaces
// Take the part of the string until the first space.
// See if it contains an underscore.
// If it does, this is the name of an operator
// delete first part of line and restart search
// https://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
// If the search reaches the end of the line,
// check if the last part of the line is the name of a correlator by doing the loop one more time
// look through at most 50 words, so the programm exits if there is no operator on the line
size_t last_part=0, j = 0;
while( key_components_counter != 2 && last_part < 2 && j < 50) {
token = linebuf.substr(0, pos);
if( token.find("_") != std::string::npos){
key_components[key_components_counter] = (std::string)token;
key_components_counter++;
}
linebuf.erase(0, pos+1);
j++;
pos = linebuf.find_first_of(delimiter);
if (pos == std::string::npos) {
last_part++;
pos = linebuf.length();
}
}
if(key_components_counter != 2){
char message[200];
snprintf(message, 200, "map_file: unable to construct key components in parsing of '%s'", linebuf.c_str());
stop(message);
}
} else {
// the line looks like so:
// " # P5S0"
std::string::size_type last_space_pos = linebuf.find_last_of(" ");
std::string spin_comb = linebuf.substr(last_space_pos+1);
// now we can build the key
std::string key = make_key_newcorr(key_components[0], key_components[1], spin_comb);

// and store the position after the current newline as the starting point
// of the present correlator
filemap[ key ] = ifs.tellg();
}
} // found commented line
} //while good
} // if corrtype==2
}

/**
Expand All @@ -142,8 +229,14 @@ NumericMatrix read_nissa_textcf_kernel(
CharacterVector file_basenames_to_read,
CharacterVector smear_combs_to_read,
const unsigned int nts,
DataFrame combs_to_read)
DataFrame combs_to_read,
size_t corrtype = 1)
{
if (corrtype != 1 && corrtype != 2){
char message[200];
snprintf(message, 200, "No valid corrtype was given! You gave %lu, valid corrtypes are 1 for 2pt and 2 for newcorr", corrtype);
stop(message);
}

const unsigned int n_correls = combs_to_read.nrows();
const unsigned int n_smear_combs = smear_combs_to_read.size();
Expand All @@ -153,18 +246,32 @@ NumericMatrix read_nissa_textcf_kernel(
NumericMatrix cf_data(n_files, 2*nts*n_correls*n_smear_combs );

CharacterVector spin_combs = combs_to_read["spin_comb"];
IntegerVector r1_idcs = combs_to_read["r1_idx"];
IntegerVector r2_idcs = combs_to_read["r2_idx"];
IntegerVector m1_idcs = combs_to_read["m1_idx"];
IntegerVector m2_idcs = combs_to_read["m2_idx"];
CharacterVector op1_idcs, op2_idcs;
IntegerVector r1_idcs, r2_idcs, m1_idcs, m2_idcs;
// different correlator naming schemes require different input: type 1 needs info on all r, m, type 2 needs names, both need spin comb
if (corrtype == 1) {
r1_idcs = combs_to_read["r1_idx"];
r2_idcs = combs_to_read["r2_idx"];
m1_idcs = combs_to_read["m1_idx"];
m2_idcs = combs_to_read["m2_idx"];
}
if (corrtype == 2){
op1_idcs = combs_to_read["op1_idx"];
op2_idcs = combs_to_read["op2_idx"];
}

std::vector<double> realbuf(nts);
std::vector<double> imagbuf(nts);

for(unsigned int ifile = 0; ifile < n_files; ++ifile ){
for(unsigned int ismear_comb = 0; ismear_comb < n_smear_combs; ++ismear_comb ){

std::string filename = (std::string)(file_basenames_to_read[ifile]) + std::string("_") +
std::string filename;

//for type 2: use smear_comb to indicate file ending
if(corrtype == 1) filename = (std::string)(file_basenames_to_read[ifile]) + std::string("_") +
(std::string)(smear_combs_to_read[ismear_comb]);
if(corrtype == 2) filename = (std::string)(file_basenames_to_read[ifile]) + std::string("/") +
(std::string)(smear_combs_to_read[ismear_comb]);

std::ifstream ifs(filename.c_str(), std::ios::in);
Expand All @@ -178,7 +285,7 @@ NumericMatrix read_nissa_textcf_kernel(
// to a certain position in the file by reading the meta-data
// this is a significant overhead incurred on a per-file basis,
// but it is robust against changes in the file's structure
map_file(ifs, filemap);
map_file(ifs, filemap, corrtype=corrtype);
// bring file back into good state
ifs.clear();

Expand All @@ -190,11 +297,19 @@ NumericMatrix read_nissa_textcf_kernel(
// if we ever support other correlation functions from Nissa,
// a simple point to generalise would be here in the way the key is
// constructed
std::string key = make_key_2pt((unsigned int)m1_idcs[icorrel],
(unsigned int)m2_idcs[icorrel],
(unsigned int)r1_idcs[icorrel],
(unsigned int)r2_idcs[icorrel],
(std::string)spin_combs[icorrel]);
std::string key;
if(corrtype==1){
key = make_key_2pt((unsigned int)m1_idcs[icorrel],
(unsigned int)m2_idcs[icorrel],
(unsigned int)r1_idcs[icorrel],
(unsigned int)r2_idcs[icorrel],
(std::string)spin_combs[icorrel]);
}
if(corrtype==2){
key = make_key_newcorr((std::string)op1_idcs[icorrel],
(std::string)op2_idcs[icorrel],
(std::string)spin_combs[icorrel]);
}
if( filemap.count(key) != 1 ){
char message[200];
snprintf(message, 200, "correlator %s does not exist in file %s!", key.c_str(), filename.c_str());
Expand Down