diff options
Diffstat (limited to 'src/kondo.c')
-rw-r--r-- | src/kondo.c | 1449 |
1 files changed, 1449 insertions, 0 deletions
diff --git a/src/kondo.c b/src/kondo.c new file mode 100644 index 0000000..c86b4b3 --- /dev/null +++ b/src/kondo.c @@ -0,0 +1,1449 @@ +/* +Copyright 2015 Ian Jauslin + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "kondo.h" +#include <stdlib.h> +#include <stdio.h> + +#include "idtable.h" +#include "array.h" +#include "number.h" +#include "istring.h" +#include "cli_parser.h" +#include "fields.h" +#include "parse_file.h" +#include "polynomial.h" +#include "definitions.cpp" +#include "rational.h" + +// dimension of A, B and h (must be <10) +#define KONDO_DIM 3 +// number of spin components +#define KONDO_SPIN 2 + +// offsets for indices of A, B and h +// order matters for symbols table +#define KONDO_A_OFFSET 1 +#define KONDO_B_OFFSET 2 +#define KONDO_H_OFFSET 3 + +// parsing modes (from parse_file.c) +#define PP_NULL_MODE 0 +// when reading a factor +#define PP_FACTOR_MODE 1 +// reading a monomial +#define PP_MONOMIAL_MODE 2 +// reading a numerator and denominator +#define PP_NUMBER_MODE 3 +// types of fields +#define PP_FIELD_MODE 6 +#define PP_PARAMETER_MODE 7 +#define PP_EXTERNAL_MODE 8 +#define PP_INTERNAL_MODE 9 +// indices +#define PP_INDEX_MODE 10 +// factors or monomials +#define PP_BRACKET_MODE 11 +// labels +#define PP_LABEL_MODE 12 +// polynomial +#define PP_POLYNOMIAL_MODE 13 +// field scalar product +#define PP_FIELD_SCALAR_MODE 14 +#define PP_FIELD_VECTOR_PROD_MODE 15 + + + +// generate configuration file +int kondo_generate_conf(Str_Array* str_args, int box_count){ + Str_Array new_args; + Fields_Table fields; + Char_Array tmp_str; + int arg_index; + int i; + Char_Array title; + + init_Str_Array(&new_args,8); + + // fields + kondo_fields_table(box_count, &tmp_str, &fields); + str_array_append_noinit(tmp_str, &new_args); + + // symbols + kondo_symbols(&tmp_str, box_count, &fields); + arg_index=find_str_arg("symbols", *str_args); + if(arg_index>=0){ + if(tmp_str.length>0){ + char_array_snprintf(&tmp_str,",\n"); + } + char_array_concat((*str_args).strs[arg_index], &tmp_str); + } + parse_input_symbols(tmp_str, &fields); + str_array_append_noinit(tmp_str, &new_args); + + // identities + kondo_identities(&tmp_str); + arg_index=find_str_arg("identities", *str_args); + if(arg_index>=0){ + if(tmp_str.length>0){ + char_array_snprintf(&tmp_str,",\n"); + } + char_array_concat((*str_args).strs[arg_index], &tmp_str); + } + parse_input_identities(tmp_str, &fields); + str_array_append_noinit(tmp_str, &new_args); + + // groups + kondo_groups(&tmp_str, box_count); + str_array_append_noinit(tmp_str, &new_args); + + + // propagator + arg_index=find_str_arg("propagator", *str_args); + if(arg_index>=0){ + kondo_propagator((*str_args).strs[arg_index], &tmp_str); + str_array_append_noinit(tmp_str, &new_args); + } + + // input polynomial + arg_index=find_str_arg("input_polynomial", *str_args); + if(arg_index>=0){ + kondo_input_polynomial((*str_args).strs[arg_index], &tmp_str, fields, box_count); + str_array_append_noinit(tmp_str, &new_args); + } + + // id table + arg_index=find_str_arg("id_table", *str_args); + if(arg_index>=0){ + kondo_idtable((*str_args).strs[arg_index], &tmp_str, fields); + str_array_append_noinit(tmp_str, &new_args); + } + + // copy remaining entries + for(i=0;i<(*str_args).length;i++){ + get_str_arg_title((*str_args).strs[i], &title); + if(str_cmp(title.str, "symbols")==0 &&\ + str_cmp(title.str, "identities")==0 &&\ + str_cmp(title.str, "propagator")==0 &&\ + str_cmp(title.str, "input_polynomial")==0 &&\ + str_cmp(title.str, "id_table")==0 ){ + + char_array_cpy((*str_args).strs[i], &tmp_str); + str_array_append_noinit(tmp_str, &new_args); + } + free_Char_Array(title); + } + + free_Fields_Table(fields); + free_Str_Array(*str_args); + *str_args=new_args; + + return(0); +} + + +// generate the Kondo fields table +int kondo_fields_table(int box_count, Char_Array* str_fields, Fields_Table* fields){ + int i,j; + + init_Char_Array(str_fields,STR_SIZE); + char_array_snprintf(str_fields, "#!fields\n"); + + // external fields + char_array_append_str("x:",str_fields); + for(i=0;i<KONDO_SPIN;i++){ + char_array_snprintf(str_fields, "%d,%d", 10*(i+10*KONDO_A_OFFSET), 10*(i+10*KONDO_B_OFFSET)); + if(i<KONDO_SPIN-1){ + char_array_append(',',str_fields); + } + } + char_array_append('\n',str_fields); + + // internal fields: A + char_array_append_str("i:",str_fields); + for(i=0;i<KONDO_SPIN;i++){ + for(j=1;j<=box_count;j++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_A_OFFSET)+j); + char_array_append(',',str_fields); + } + } + // B + for(i=0;i<KONDO_SPIN;i++){ + for(j=1;j<=2;j++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_B_OFFSET)+j); + if(i<KONDO_SPIN-1 || j<2){ + char_array_append(',',str_fields); + } + } + } + char_array_append('\n',str_fields); + + // parameters + char_array_append_str("h:",str_fields); + for(i=0;i<KONDO_DIM;i++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_H_OFFSET)); + if(i<KONDO_DIM-1){ + char_array_append(',',str_fields); + } + } + char_array_append('\n',str_fields); + + // declare Fermions + char_array_append_str("f:",str_fields); + // external fields + for(i=0;i<KONDO_SPIN;i++){ + char_array_snprintf(str_fields, "%d,%d", 10*(i+10*KONDO_A_OFFSET), 10*(i+10*KONDO_B_OFFSET)); + char_array_append(',',str_fields); + } + // internal fields: A + for(i=0;i<KONDO_SPIN;i++){ + for(j=1;j<=box_count;j++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_A_OFFSET)+j); + char_array_append(',',str_fields); + } + } + // B + for(i=0;i<KONDO_SPIN;i++){ + for(j=1;j<=2;j++){ + char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_B_OFFSET)+j); + if(i<KONDO_SPIN-1 || j<2){ + char_array_append(',',str_fields); + } + } + } + char_array_append('\n',str_fields); + + // parse fields table + parse_input_fields(*str_fields, fields); + + return(0); +} + + +// generate Kondo symbols +int kondo_symbols(Char_Array* str_symbols, int box_count, Fields_Table* fields){ + int i,j,k,l; + Char_Array tmp_str; + Polynomial poly; + char letters[3]={'A','B','h'}; + + init_Char_Array(str_symbols, STR_SIZE); + char_array_snprintf(str_symbols, "#!symbols\n"); + + // loop over box index + for(i=1;i<=box_count;i++){ + // loop over letters + for(j=0;j<2;j++){ + // loop over space dimension + for(k=0;k<KONDO_DIM;k++){ + // write index + char_array_snprintf(str_symbols, "%d=", 100*(10*(KONDO_A_OFFSET+j)+k)+i); + // write the name of the scalar product + init_Char_Array(&tmp_str, 6); + char_array_snprintf(&tmp_str, "%c%d%d", letters[j], k, i); + // compute corresponding polynomial + kondo_resolve_ABh(tmp_str.str, &poly, *fields); + free_Char_Array(tmp_str); + // write to output + polynomial_sprint(poly, str_symbols); + free_Polynomial(poly); + // add , + char_array_snprintf(str_symbols,",\n"); + } + } + } + + // scalar products + // loop over box index + for(i=1;i<=box_count;i++){ + // loop over letters + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + // write index + char_array_snprintf(str_symbols, "%d=", 1000*(10*(KONDO_A_OFFSET+j)+KONDO_A_OFFSET+k)+i); + for(l=0;l<KONDO_DIM;l++){ + char_array_snprintf(str_symbols, "(1)"); + if(j<2){ + char_array_snprintf(str_symbols,"[f%d]", 100*(10*(KONDO_A_OFFSET+j)+l)+i); + } + else{ + char_array_snprintf(str_symbols,"[f%d]", 10*(10*(KONDO_A_OFFSET+j)+l)); + } + if(k<2){ + char_array_snprintf(str_symbols,"[f%d]", 100*(10*(KONDO_A_OFFSET+k)+l)+i); + } + else{ + char_array_snprintf(str_symbols,"[f%d]", 10*(10*(KONDO_A_OFFSET+k)+l)); + } + + if(l<KONDO_DIM-1){ + char_array_append('+',str_symbols); + } + } + // add , + char_array_snprintf(str_symbols,",\n"); + } + } + } + + // vector products + for(i=1;i<=box_count;i++){ + char_array_snprintf(str_symbols, "%d=", 100*(100*(KONDO_A_OFFSET)+10*KONDO_B_OFFSET+KONDO_H_OFFSET)+i); + for(l=0;l<KONDO_DIM;l++){ + // remember (-1 %3 = -1) + char_array_snprintf(str_symbols, "(1)[f%d][f%d][f%d]+(-1)[f%d][f%d][f%d]", 100*(10*KONDO_A_OFFSET+((l+1)%KONDO_DIM))+i, 100*(10*KONDO_B_OFFSET+((l+2)%KONDO_DIM))+i, 10*(10*KONDO_H_OFFSET+l), 100*(10*KONDO_A_OFFSET+((l+2)%KONDO_DIM))+i, 100*(10*KONDO_B_OFFSET+((l+1)%KONDO_DIM))+i, 10*(10*KONDO_H_OFFSET+l)); + if(l<KONDO_DIM-1){ + char_array_append('+',str_symbols); + } + } + + // add , + if(i<box_count){ + char_array_snprintf(str_symbols,",\n"); + } + } + + + return(0); +} + +// generate Kondo symbols (older method: one symbol for each scalar product) +int kondo_symbols_scalarprod(Char_Array* str_symbols, int box_count, Fields_Table* fields){ + int i,j,k; + Char_Array tmp_str; + Polynomial poly; + char letters[3]={'A','B','h'}; + + init_Char_Array(str_symbols, STR_SIZE); + char_array_snprintf(str_symbols, "#!symbols\n"); + + // loop over box index + for(i=1;i<=box_count;i++){ + // loop over letters + for(j=0;j<3;j++){ + for(k=0;k<3;k++){ + // write index + char_array_snprintf(str_symbols, "%d=", 100*(10*(KONDO_A_OFFSET+j)+KONDO_A_OFFSET+k)+i); + // write the name of the scalar product + init_Char_Array(&tmp_str, 6); + char_array_snprintf(&tmp_str, "%c%d.%c%d", letters[j], i, letters[k], i); + // compute corresponding polynomial + kondo_resolve_scalar_prod(tmp_str.str, &poly, *fields); + free_Char_Array(tmp_str); + // write to output + polynomial_sprint(poly, str_symbols); + free_Polynomial(poly); + // add , + if(i<box_count || j<2 || k<2){ + char_array_snprintf(str_symbols,",\n"); + } + } + } + } + + parse_input_symbols(*str_symbols, fields); + + return(0); +} + + +// generate Kondo groups (groups of independent variables) +int kondo_groups(Char_Array* str_groups, int box_count){ + int i,j; + + init_Char_Array(str_groups, STR_SIZE); + char_array_snprintf(str_groups, "#!groups\n"); + char_array_append('(',str_groups); + for(i=0;i<KONDO_DIM;i++){ + for(j=1;j<=box_count;j++){ + char_array_snprintf(str_groups, "%d",100*(10*KONDO_A_OFFSET+i)+j); + if(j<box_count || i<KONDO_DIM-1){ + char_array_append(',',str_groups); + } + } + } + char_array_append(')',str_groups); + char_array_append('\n',str_groups); + + char_array_append('(',str_groups); + for(i=0;i<KONDO_DIM;i++){ + for(j=1;j<=box_count;j++){ + char_array_snprintf(str_groups, "%d",100*(10*KONDO_B_OFFSET+i)+j); + if(j<box_count || i<KONDO_DIM-1){ + char_array_append(',',str_groups); + } + } + } + char_array_append(')',str_groups); + char_array_append('\n',str_groups); + return(0); +} + + +// generate Kondo identities +// h_3^2=1-h_1^2-h_2^2 +int kondo_identities(Char_Array* str_identities){ + int i; + + init_Char_Array(str_identities,STR_SIZE); + char_array_snprintf(str_identities, "#!identities\n"); + + char_array_snprintf(str_identities, "[f%d][f%d]=(1)",10*(KONDO_DIM-1+10*KONDO_H_OFFSET),10*(KONDO_DIM-1+10*KONDO_H_OFFSET)); + for(i=0;i<KONDO_DIM-1;i++){ + char_array_snprintf(str_identities, "+(-1)[f%d][f%d]",10*(i+10*KONDO_H_OFFSET),10*(i+10*KONDO_H_OFFSET)); + } + + return(0); +} + + +// convert the Kondo propagator +int kondo_propagator(Char_Array str_kondo_propagator, Char_Array* str_propagator){ + int i,j; + // buffer + char* buffer=calloc(str_kondo_propagator.length+1,sizeof(char)); + char* buffer_ptr=buffer; + // offset and index for each element + int offset[2]={-1,-1}; + int index[2]={-1,-1}; + int mode; + int comment=0; + + // allocate memory + init_Char_Array(str_propagator,STR_SIZE); + + // reproduce the loop from parse_input_propagatore but merely copy values, and replace indices + mode=PP_INDEX_MODE; + for(j=0;j<str_kondo_propagator.length;j++){ + if(comment==1){ + // write comments to str + char_array_append(str_kondo_propagator.str[j],str_propagator); + if(str_kondo_propagator.str[j]=='\n'){ + comment=0; + } + } + else{ + switch(str_kondo_propagator.str[j]){ + // indices + case ';': + if(mode==PP_INDEX_MODE){ + get_offset_index(buffer,offset,index); + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + case ':': + if(mode==PP_INDEX_MODE){ + get_offset_index(buffer,offset+1,index+1); + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_NUMBER_MODE; + } + break; + + // num + case ',': + if(mode==PP_NUMBER_MODE && offset[0]>=0 && offset[1]>=0 && index[0]>=0 && index[1]>=0){ + // write indices and num + for(i=0;i<KONDO_SPIN;i++){ + char_array_snprintf(str_propagator,"%d;%d:%s,",10*(i+10*offset[0])+index[0], 10*(i+10*offset[1])+index[1], buffer); + } + buffer_ptr=buffer; + *buffer_ptr='\0'; + mode=PP_INDEX_MODE; + } + break; + + // comment + case '#': + comment=1; + char_array_append(str_kondo_propagator.str[j],str_propagator); + break; + + // ignore line breaks + case '\n': break; + + default: + buffer_ptr=str_addchar(buffer_ptr,str_kondo_propagator.str[j]); + break; + } + } + } + + // last step + if(mode==PP_NUMBER_MODE){ + for(i=0;i<KONDO_SPIN;i++){ + char_array_snprintf(str_propagator,"%d;%d:%s",10*(i+10*offset[0])+index[0], 10*(i+10*offset[1])+index[1], buffer); + if(i<KONDO_SPIN-1){ + char_array_append(',',str_propagator); + } + } + } + + free(buffer); + return(0); + +} + + +// convert Kondo input polynomial +int kondo_input_polynomial(Char_Array str_kondo_polynomial, Char_Array* str_polynomial, Fields_Table fields, int box_count){ + Polynomial tmp_poly; + Polynomial out_poly; + Char_Array tmp_str_kondo_polynomial; + int i; + // whether there is a '%' in the input polynomial + int star=0; + + init_Char_Array(str_polynomial, STR_SIZE); + char_array_snprintf(str_polynomial, "#!input_polynomial\n"); + + // check for a '%' + for(i=0;i<str_kondo_polynomial.length;i++){ + if(str_kondo_polynomial.str[i]=='%'){ + star=1; + break; + } + } + + // if there is a '%', then take a product over boxes + if(star==1){ + // product over i from 1 to box_count + for(i=1;i<=box_count;i++){ + // replace '%' with the appropriate index + replace_star('0'+i,str_kondo_polynomial, &tmp_str_kondo_polynomial); + // read polynomial + parse_kondo_polynomial_factors(tmp_str_kondo_polynomial, &tmp_poly, fields); + + // product + if(i==1){ + polynomial_cpy(tmp_poly,&out_poly); + } + else{ + polynomial_prod_chain(tmp_poly,&out_poly, fields); + } + + free_Polynomial(tmp_poly); + free_Char_Array(tmp_str_kondo_polynomial); + } + } + // if no '%' then read polynomial as is + else{ + parse_kondo_polynomial_factors(str_kondo_polynomial, &out_poly, fields); + } + + // useful simplification + remove_unmatched_plusminus(&out_poly, fields); + polynomial_sprint(out_poly, str_polynomial); + free_Polynomial(out_poly); + return(0); +} + + +// convert the Kondo idtable +int kondo_idtable(Char_Array str_kondo_idtable, Char_Array* str_idtable, Fields_Table fields){ + int j; + // buffer + char* buffer=calloc(str_kondo_idtable.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Polynomial tmp_poly; + int mode; + + // allocate memory + init_Char_Array(str_idtable,STR_SIZE); + + // reproduce the loop from parse_input_id_table but merely copy labels and indices, and replace Kondo polynomials + mode=PP_INDEX_MODE; + for(j=0;j<str_kondo_idtable.length;j++){ + // unless inside a polynomial write to output + if(mode!=PP_POLYNOMIAL_MODE){ + char_array_append(str_kondo_idtable.str[j],str_idtable); + } + + switch(str_kondo_idtable.str[j]){ + // end polynomial mode + case ',': + if(mode==PP_POLYNOMIAL_MODE){ + mode=PP_INDEX_MODE; + // write polynomial + parse_kondo_polynomial_str(buffer, &tmp_poly, fields); + polynomial_sprint(tmp_poly, str_idtable); + free_Polynomial(tmp_poly); + char_array_append(',',str_idtable); + } + break; + + case ':': + if(mode==PP_INDEX_MODE){ + mode=PP_POLYNOMIAL_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + + default: + if(mode==PP_POLYNOMIAL_MODE){ + buffer_ptr=str_addchar(buffer_ptr,str_kondo_idtable.str[j]); + } + break; + } + } + + //last step + if(mode==PP_POLYNOMIAL_MODE){ + parse_kondo_polynomial_str(buffer, &tmp_poly, fields); + polynomial_sprint(tmp_poly, str_idtable); + free_Polynomial(tmp_poly); + } + + free(buffer); + return(0); +} + +// read a product of polynomials +int parse_kondo_polynomial_factors(Char_Array str_polynomial, Polynomial* output, Fields_Table fields){ + int j; + // buffer + char* buffer=calloc(str_polynomial.length+1,sizeof(char)); + char* buffer_ptr=buffer; + Polynomial tmp_poly; + + // allocate memory + init_Polynomial(output,POLY_SIZE); + + for(j=0;j<str_polynomial.length;j++){ + switch(str_polynomial.str[j]){ + case '*': + parse_kondo_polynomial_str(buffer, &tmp_poly, fields); + if((*output).length==0){ + polynomial_concat(tmp_poly, output); + } + else{ + polynomial_prod_chain(tmp_poly, output, fields); + } + free_Polynomial(tmp_poly); + + buffer_ptr=buffer; + *buffer_ptr='\0'; + break; + + default: + buffer_ptr=str_addchar(buffer_ptr,str_polynomial.str[j]); + break; + } + } + + //last step + parse_kondo_polynomial_str(buffer, &tmp_poly, fields); + if((*output).length==0){ + polynomial_concat(tmp_poly, output); + } + else{ + polynomial_prod_chain(tmp_poly, output, fields); + } + free_Polynomial(tmp_poly); + + free(buffer); + return(0); +} + + +// read a kondo polynomial and convert it to a polynomial expressed in terms of the fields in the fields table +int parse_kondo_polynomial_str(char* str_polynomial, Polynomial* output, Fields_Table fields){ + // input pointer + char* polynomial_ptr; + // buffer + char* buffer=calloc(str_len(str_polynomial),sizeof(char)); + char* buffer_ptr=buffer; + int mode; + int comment=0; + int parenthesis_count=0; + int i; + int offset1, offset2; + int index; + Polynomial tmp_poly; + Number tmp_num, tmp1_num; + Int_Array tmp_factor, tmp_monomial, dummy_factor; + Polynomial scalar_prod_poly; + + // allocate memory + init_Polynomial(output,POLY_SIZE); + + init_Polynomial(&tmp_poly,MONOMIAL_SIZE); + tmp_num=number_one(); + init_Int_Array(&tmp_factor, MONOMIAL_SIZE); + + *buffer_ptr='\0'; + // loop over the input polynomial + // start in null mode + mode=PP_NULL_MODE; + for(polynomial_ptr=str_polynomial;*polynomial_ptr!='\0';polynomial_ptr++){ + if(comment==1){ + if(*polynomial_ptr=='\n'){ + comment=0; + } + } + else{ + switch(*polynomial_ptr){ + // new monomial + case '+': + if(mode==PP_NULL_MODE){ + // if not a constant + if(tmp_poly.length>0){ + // write num + polynomial_multiply_scalar(tmp_poly, tmp_num); + // replace factor + for(i=0;i<tmp_poly.length;i++){ + free_Int_Array(tmp_poly.factors[i]); + int_array_cpy(tmp_factor,tmp_poly.factors+i); + } + } + // if constant + else{ + init_Int_Array(&tmp_monomial,1); + polynomial_append(tmp_monomial,tmp_factor,tmp_num,&tmp_poly); + free_Int_Array(tmp_monomial); + } + free_Int_Array(tmp_factor); + free_Number(tmp_num); + // write polynomial + polynomial_concat_noinit(tmp_poly, output); + // reset tmp_poly + init_Polynomial(&tmp_poly,MONOMIAL_SIZE); + tmp_num=number_one(); + init_Int_Array(&tmp_factor,MONOMIAL_SIZE); + } + break; + + // numerical pre-factor + case '(': + if(mode==PP_NULL_MODE){ + mode=PP_NUMBER_MODE; + parenthesis_count=0; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + else if(mode==PP_NUMBER_MODE){ + // match parentheses + parenthesis_count++; + } + break; + case ')': + if(mode==PP_NUMBER_MODE){ + if(parenthesis_count==0){ + // write num + str_to_Number(buffer,&tmp1_num); + number_prod_chain(tmp1_num,&tmp_num); + free_Number(tmp1_num); + // back to null mode + mode=PP_NULL_MODE; + } + else{ + parenthesis_count--; + } + } + break; + + // enter factor mode + case '[': + if(mode==PP_NULL_MODE){ + mode=PP_BRACKET_MODE; + } + break; + // factor mode + case 'l': + if(mode==PP_BRACKET_MODE){ + mode=PP_FACTOR_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + // symbol mode + case 'f': + if(mode==PP_BRACKET_MODE){ + mode=PP_FIELD_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + // read factor + case ']': + // factor + if(mode==PP_FACTOR_MODE){ + sscanf(buffer,"%d",&i); + int_array_append(i,&tmp_factor); + } + // symbol + else if(mode==PP_FIELD_MODE){ + // if polynomial exists, add to each monomial + if(tmp_poly.length>0){ + for(i=0;i<tmp_poly.length;i++){ + int_array_append(get_symbol_index(buffer), tmp_poly.monomials+i); + } + } + // if not, create a new term in the polynomial + else{ + init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); + int_array_append(get_symbol_index(buffer), &tmp_monomial); + init_Int_Array(&dummy_factor, 1); + polynomial_append_noinit(tmp_monomial, dummy_factor, number_one(), &tmp_poly); + } + } + // scalar product of symbols + else if(mode==PP_FIELD_SCALAR_MODE || mode==PP_FIELD_VECTOR_PROD_MODE){ + get_offsets_index(buffer, &offset1, &offset2, &index); + // if polynomial exists, add to each monomial + if(tmp_poly.length>0){ + for(i=0;i<tmp_poly.length;i++){ + if(mode==PP_FIELD_SCALAR_MODE){ + if(offset1!=KONDO_H_OFFSET || offset2!=KONDO_H_OFFSET){ + int_array_append(1000*(10*offset1+offset2)+index, tmp_poly.monomials+i); + } + } + else{ + int_array_append(100*(100*KONDO_A_OFFSET+10*KONDO_B_OFFSET+KONDO_H_OFFSET)+index, tmp_poly.monomials+i); + } + } + } + // if not, create a new term in the polynomial + else{ + init_Int_Array(&tmp_monomial, MONOMIAL_SIZE); + if(mode==PP_FIELD_SCALAR_MODE){ + if(offset1!=KONDO_H_OFFSET || offset2!=KONDO_H_OFFSET){ + int_array_append(1000*(10*offset1+offset2)+index, &tmp_monomial); + } + } + else{ + int_array_append(100*(100*KONDO_A_OFFSET+10*KONDO_B_OFFSET+KONDO_H_OFFSET)+index, &tmp_monomial); + } + init_Int_Array(&dummy_factor, 1); + polynomial_append_noinit(tmp_monomial, dummy_factor, number_one(), &tmp_poly); + } + /* // older method in which a scalar product was expanded in A, B and h + // resolve scalar product + kondo_resolve_scalar_prod_symbols(buffer, &scalar_prod_poly); + // add to tmp_poly + if(tmp_poly.length==0){ + polynomial_concat(scalar_prod_poly,&tmp_poly); + } + else{ + polynomial_prod_chain(scalar_prod_poly,&tmp_poly,fields); + } + free_Polynomial(scalar_prod_poly); + */ + } + // switch back to null mode + mode=PP_NULL_MODE; + break; + + // symbol scalar product + case '.': + if(mode==PP_FIELD_MODE){ + mode=PP_FIELD_SCALAR_MODE; + } + buffer_ptr=str_addchar(buffer_ptr,*polynomial_ptr); + break; + case 'x': + if(mode==PP_FIELD_MODE){ + mode=PP_FIELD_VECTOR_PROD_MODE; + } + buffer_ptr=str_addchar(buffer_ptr,*polynomial_ptr); + break; + + // scalar product + case '<': + if(mode==PP_NULL_MODE){ + mode=PP_MONOMIAL_MODE; + buffer_ptr=buffer; + *buffer_ptr='\0'; + } + break; + case '>': + if(mode==PP_MONOMIAL_MODE){ + // resolve scalar product + kondo_resolve_scalar_prod(buffer, &scalar_prod_poly, fields); + // add to tmp_poly + if(tmp_poly.length==0){ + polynomial_concat(scalar_prod_poly,&tmp_poly); + } + else{ + polynomial_prod_chain(scalar_prod_poly,&tmp_poly,fields); + } + free_Polynomial(scalar_prod_poly); + + mode=PP_NULL_MODE; + } + break; + + // characters to ignore + case ' ':break; + case '&':break; + case '\n':break; + + // comments + case '#': + comment=1; + break; + + default: + if(mode!=PP_NULL_MODE){ + // write to buffer + buffer_ptr=str_addchar(buffer_ptr,*polynomial_ptr); + } + break; + } + } + } + + // last term + if(tmp_poly.length>0){ + polynomial_multiply_scalar(tmp_poly,tmp_num); + for(i=0;i<tmp_poly.length;i++){ + free_Int_Array(tmp_poly.factors[i]); + int_array_cpy(tmp_factor,tmp_poly.factors+i); + } + } + else{ + init_Int_Array(&tmp_monomial,1); + polynomial_append(tmp_monomial,tmp_factor,tmp_num,&tmp_poly); + } + free_Int_Array(tmp_factor); + free_Number(tmp_num); + polynomial_concat_noinit(tmp_poly, output); + + // simplify + polynomial_simplify(output, fields); + + free(buffer); + return(0); +} + +// as Char_Array +int parse_kondo_polynomial(Char_Array kondo_polynomial_str, Polynomial* polynomial, Fields_Table fields){ + char* str; + char_array_to_str(kondo_polynomial_str, &str); + parse_kondo_polynomial_str(str, polynomial, fields); + free(str); + return(0); +} + + +// read Aij, Bij, hi where i is a space dimension and j is a box index +int kondo_resolve_ABh(char* str, Polynomial* output, Fields_Table fields){ + char* ptr; + // offset (A,B or H) + int offset=-1; + // dimension + int dim=-1; + // box index + int index=-1; + // polynomial for each term + Polynomial psi[KONDO_SPIN]; + Polynomial poly_conjugate; + Int_Array monomial; + Int_Array factor; + Number_Matrix pauli_mat; + int i,a,b; + + // memory + init_Polynomial(output, MONOMIAL_SIZE); + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset=KONDO_A_OFFSET; + break; + case 'a': + offset=KONDO_A_OFFSET; + break; + case 'B': + offset=KONDO_B_OFFSET; + break; + case 'b': + offset=KONDO_B_OFFSET; + break; + case 'h': + offset=KONDO_H_OFFSET; + break; + default: + // set index if dim was already set + if(dim>=0){ + index=*ptr-'0'; + } + else{ + dim=*ptr-'0'; + } + } + } + + // turn B3 into B2 and B4 into B1 + if(offset==KONDO_B_OFFSET){ + switch(index){ + case 3: + index=2; + break; + case 4: + index=1; + break; + } + } + + // h's + if(offset==KONDO_H_OFFSET){ + // external field + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + int_array_append(10*(dim+10*offset), &monomial); + polynomial_append_noinit(monomial, factor, number_one(), output); + } + // psi's + else{ + // construct spin indices + for(i=0;i<KONDO_SPIN;i++){ + init_Polynomial(psi+i,2); + + // external field + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + int_array_append(10*(i+10*offset), &monomial); + polynomial_append_noinit(monomial, factor, number_one(), psi+i); + + // internal field if applicable + if(index>0){ + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + + int_array_append(10*(i+10*offset)+index, &monomial); + polynomial_append_noinit(monomial, factor, number_one(), psi+i); + } + } + + // multiply by Pauli matrices + Pauli_matrix(dim+1,&pauli_mat); + for(a=0;a<KONDO_SPIN;a++){ + for(b=0;b<KONDO_SPIN;b++){ + polynomial_cpy(psi[b],&poly_conjugate); + polynomial_conjugate(poly_conjugate); + polynomial_multiply_scalar(poly_conjugate, pauli_mat.matrix[a][b]); + polynomial_prod_chain(psi[a],&poly_conjugate,fields); + // add to poly + polynomial_concat_noinit(poly_conjugate, output); + } + } + + free_Number_Matrix(pauli_mat); + + // free spin indices + for(i=0;i<KONDO_SPIN;i++){ + free_Polynomial(psi[i]); + } + } + + return(0); +} + +#define K_VECT_PROD 1 +#define K_SCALAR_PROD 2 +// read a Kondo scalar product (generalized to vector products as well) +int kondo_resolve_scalar_prod(char* str, Polynomial* output, Fields_Table fields){ + char* ptr; + // offset of each term (A,B or H) + int offset=-1; + // index of each term (0,...,box_count) + int index=0; + int i; + int operation=0; + Polynomial poly_vect1[KONDO_DIM]; + Polynomial poly_vect2[KONDO_DIM]; + + // memory + init_Polynomial(output, MONOMIAL_SIZE); + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset=KONDO_A_OFFSET; + break; + case 'a': + offset=KONDO_A_OFFSET; + break; + case 'B': + offset=KONDO_B_OFFSET; + break; + case 'b': + offset=KONDO_B_OFFSET; + break; + case 'h': + offset=KONDO_H_OFFSET; + break; + + // scalar product + case '.': + // if no previous vector product + if(operation!=K_VECT_PROD){ + kondo_polynomial_vector(offset, index, &poly_vect1, fields); + } + // compute vector product + else{ + kondo_polynomial_vector(offset, index, &poly_vect2, fields); + kondo_polynomial_vector_product(&poly_vect1, poly_vect2, fields); + } + operation=K_SCALAR_PROD; + break; + + // vector product + case 'x': + if(offset>=0){ + kondo_polynomial_vector(offset, index, &poly_vect1, fields); + operation=K_VECT_PROD; + } + break; + + // index + default: + // char to int + index=*ptr-'0'; + } + } + + // final scalar product + if(operation==K_SCALAR_PROD){ + if(offset>=0){ + kondo_polynomial_vector(offset, index, &poly_vect2, fields); + kondo_polynomial_scalar_product(poly_vect1, poly_vect2, output, fields); + } + } + + // free memory + for(i=0;i<KONDO_DIM;i++){ + free_Polynomial(poly_vect1[i]); + free_Polynomial(poly_vect2[i]); + } + + return(0); +} + +// compute a scalar product of polynomial vectors +int kondo_polynomial_scalar_product(Polynomial poly_vect1[3], Polynomial poly_vect2[3], Polynomial* output, Fields_Table fields){ + int i; + Polynomial tmp_poly; + + for(i=0;i<KONDO_DIM;i++){ + polynomial_prod(poly_vect1[i],poly_vect2[i],&tmp_poly,fields); + + // add to output + polynomial_concat_noinit(tmp_poly, output); + } + + polynomial_simplify(output, fields); + + return(0); +} + +// compute a vector product of polynomial vectors +int kondo_polynomial_vector_product(Polynomial (*poly_vect1)[3], Polynomial poly_vect2[3], Fields_Table fields){ + int i; + Polynomial out[3]; + Polynomial tmp_poly; + + for(i=0;i<3;i++){ + init_Polynomial(out+i, POLY_SIZE); + + polynomial_prod((*poly_vect1)[(i+1)%3],poly_vect2[(i+2)%3], &tmp_poly, fields); + polynomial_concat_noinit(tmp_poly, out+i); + + polynomial_prod((*poly_vect1)[(i+2)%3],poly_vect2[(i+1)%3], &tmp_poly, fields); + polynomial_multiply_Qscalar(tmp_poly,quot(-1,1)); + polynomial_concat_noinit(tmp_poly, out+i); + } + + for(i=0;i<3;i++){ + free_Polynomial((*poly_vect1)[i]); + (*poly_vect1)[i]=out[i]; + } + + return(0); +} + +// compute the 3 components of a kondo vector +int kondo_polynomial_vector(int offset, int index, Polynomial (*polys)[3], Fields_Table fields){ + int i,a,b; + // polynomial for each term + Polynomial psi[KONDO_SPIN]; + Polynomial poly_conjugate; + Int_Array monomial; + Int_Array factor; + Number_Matrix pauli_mat; + + for(i=0;i<KONDO_DIM;i++){ + // memory + init_Polynomial((*polys)+i,POLY_SIZE); + } + + // h's + if(offset==KONDO_H_OFFSET){ + // construct every component field + for(i=0;i<KONDO_DIM;i++){ + // external field + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + int_array_append(10*(i+10*offset), &monomial); + polynomial_append_noinit(monomial, factor, number_one(), (*polys)+i); + } + } + // psi's + else{ + // construct spin indices + for(i=0;i<KONDO_SPIN;i++){ + init_Polynomial(psi+i,2); + + // external field + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + int_array_append(10*(i+10*offset), &monomial); + polynomial_append_noinit(monomial, factor, number_one(), psi+i); + + // internal field if applicable + if(index>0){ + init_Int_Array(&monomial,1); + init_Int_Array(&factor,1); + + int_array_append(10*(i+10*offset)+index, &monomial); + polynomial_append_noinit(monomial, factor, number_one(), psi+i); + } + } + + // multiply by Pauli matrices + for(i=0;i<KONDO_DIM;i++){ + Pauli_matrix(i+1,&pauli_mat); + for(a=0;a<KONDO_SPIN;a++){ + for(b=0;b<KONDO_SPIN;b++){ + polynomial_cpy(psi[b],&poly_conjugate); + polynomial_conjugate(poly_conjugate); + polynomial_multiply_scalar(poly_conjugate, pauli_mat.matrix[a][b]); + polynomial_prod_chain(psi[a],&poly_conjugate,fields); + // add to polys[j] + polynomial_concat_noinit(poly_conjugate, (*polys)+i); + } + } + + free_Number_Matrix(pauli_mat); + } + + // free spin indices + for(i=0;i<KONDO_SPIN;i++){ + free_Polynomial(psi[i]); + } + } + + return(0); +} + +// read a scalar product of symbols +int kondo_resolve_scalar_prod_symbols(char* str, Polynomial* output){ + char* ptr; + // first or second term + int term=0; + // offset of each term (A,B or H) + int offset[2]; + // index of each term (0,...,box_count) + int index[2]={0,0}; + Int_Array monomial; + Int_Array factor; + int i; + + // memory + init_Polynomial(output, KONDO_DIM); + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset[term]=KONDO_A_OFFSET; + break; + case 'a': + offset[term]=KONDO_A_OFFSET; + break; + case 'B': + offset[term]=KONDO_B_OFFSET; + break; + case 'b': + offset[term]=KONDO_B_OFFSET; + break; + case 'h': + offset[term]=KONDO_H_OFFSET; + break; + // switch term + case '.': + term=1-term; + break; + default: + // char to int + index[term]=*ptr-'0'; + } + } + + // scalar product + for(i=0;i<KONDO_DIM;i++){ + init_Int_Array(&monomial,2); + init_Int_Array(&factor, 1); + + if(offset[0]==KONDO_H_OFFSET){ + int_array_append(10*(10*offset[0]+i)+index[0], &monomial); + } + else{ + int_array_append(100*(10*offset[0]+i)+index[0], &monomial); + } + if(offset[1]==KONDO_H_OFFSET){ + int_array_append(10*(10*offset[1]+i)+index[1], &monomial); + } + else{ + int_array_append(100*(10*offset[1]+i)+index[1], &monomial); + } + + polynomial_append_noinit(monomial, factor, number_one(), output); + } + return(0); +} + +// get the offset and index of a monomial term +// (e.g. A1 yields KONDO_A_OFFSET and 1) +int get_offset_index(char* str, int* offset, int* index){ + char* ptr; + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + *offset=KONDO_A_OFFSET; + break; + case 'a': + *offset=KONDO_A_OFFSET; + break; + case 'B': + *offset=KONDO_B_OFFSET; + break; + case 'b': + *offset=KONDO_B_OFFSET; + break; + case 'h': + *offset=KONDO_H_OFFSET; + break; + default: + // char to int + *index=*ptr-'0'; + } + } + + return(0); +} + +// get the offsets and index of a scalar product +int get_offsets_index(char* str, int* offset1, int* offset2, int* index){ + int offset[2]={-1,-1}; + char* ptr; + int term=0; + + *index=-1; + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset[term]=KONDO_A_OFFSET; + break; + case 'a': + offset[term]=KONDO_A_OFFSET; + break; + case 'B': + offset[term]=KONDO_B_OFFSET; + break; + case 'b': + offset[term]=KONDO_B_OFFSET; + break; + case 'h': + offset[term]=KONDO_H_OFFSET; + break; + // switch term + case '.': + term=1-term; + break; + default: + // char to int + *index=*ptr-'0'; + } + } + + *offset1=offset[0]; + *offset2=offset[1]; + + return(0); +} + +// get the index of the symbol corresponding to a given string +int get_symbol_index(char* str){ + char* ptr; + int offset=-1; + int index=0; + int dim=-1; + + // first check whether the field already is an index + for(ptr=str;*ptr!='\0';ptr++){ + if((*ptr-'0'>=10 || *ptr-'0'<0) && (*ptr!='-')){ + break; + } + } + if(*ptr=='\0'){ + sscanf(str,"%d",&index); + return(index); + } + + for(ptr=str;*ptr!='\0';ptr++){ + switch(*ptr){ + case 'A': + offset=KONDO_A_OFFSET; + break; + case 'a': + offset=KONDO_A_OFFSET; + break; + case 'B': + offset=KONDO_B_OFFSET; + break; + case 'b': + offset=KONDO_B_OFFSET; + break; + case 'h': + offset=KONDO_H_OFFSET; + break; + default: + // set index if dim was already set + if(dim>=0){ + index=*ptr-'0'; + } + else{ + dim=*ptr-'0'; + } + } + } + + if(offset==-1){ + return(-1); + } + // no symbol for h + if(offset==KONDO_H_OFFSET){ + return(10*(10*offset+dim)); + } + else{ + return(100*(10*offset+dim)+index); + } +} |