meankondo/src/kondo.c
2015-07-22 13:55:29 +00:00

1450 lines
35 KiB
C

/*
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, h and t (must be <10)
#define KONDO_DIM 3
// number of spin components
#define KONDO_SPIN 2
// offsets for indices of A, B, h and t
// order matters for symbols table
#define KONDO_A_OFFSET 1
#define KONDO_B_OFFSET 2
#define KONDO_H_OFFSET 3
#define KONDO_T_OFFSET 4
// 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);
// h
for(i=0;i<KONDO_DIM;i++){
char_array_snprintf(str_fields, "%d,", 10*(i+10*KONDO_H_OFFSET));
}
// t
for(i=0;i<KONDO_DIM;i++){
char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_T_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);
// declare noncommuting
char_array_append_str("a:",str_fields);
for(i=0;i<KONDO_DIM;i++){
char_array_snprintf(str_fields, "%d", 10*(i+10*KONDO_T_OFFSET));
if(i<KONDO_DIM-1){
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 (A and B)
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_ABht(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 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
// and Pauli matrices
int kondo_identities(Char_Array* str_identities){
int i;
init_Char_Array(str_identities,STR_SIZE);
char_array_snprintf(str_identities, "#!identities\n");
// Pauli matrices
for(i=0;i<KONDO_DIM;i++){
char_array_snprintf(str_identities,"[f%d][f%d]=(1),\n",10*(10*KONDO_T_OFFSET+i),10*(10*KONDO_T_OFFSET+i));
char_array_snprintf(str_identities,"[f%d][f%d]=(s{-1})[f%d],\n",10*(10*KONDO_T_OFFSET+i),10*(10*KONDO_T_OFFSET+(i+1)%3),10*(10*KONDO_T_OFFSET+(i+2)%3));
char_array_snprintf(str_identities,"[f%d][f%d]=((-1)s{-1})[f%d],\n",10*(10*KONDO_T_OFFSET+(i+2)%3),10*(10*KONDO_T_OFFSET+(i+1)%3),10*(10*KONDO_T_OFFSET+i));
}
// h
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){
int_array_append(1000*(10*offset1+offset2)+index, tmp_poly.monomials+i);
}
else{
// vector product
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){
int_array_append(1000*(10*offset1+offset2)+index, &tmp_monomial);
}
else{
// vector product
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);
}
}
// 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, ti where i is a space dimension and j is a box index
int kondo_resolve_ABht(char* str, Polynomial* output, Fields_Table fields){
char* ptr;
// offset (A,B, H or T)
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;
case 't':
offset=KONDO_T_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 and t's
if(offset==KONDO_H_OFFSET || offset==KONDO_T_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);
// correct sign: psi[a]^+ should be on the left of psi[b]^-
polynomial_multiply_Qscalar(poly_conjugate,quot(-1,1));
// 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,H or T)
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;
case 't':
offset=KONDO_T_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 and t's
if(offset==KONDO_H_OFFSET || offset==KONDO_T_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);
// correct sign: psi[a]^+ should be on the left of psi[b]^-
polynomial_multiply_Qscalar(poly_conjugate,quot(-1,1));
// 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,H or T)
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;
case 't':
offset[term]=KONDO_T_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 || offset[0]==KONDO_T_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 || offset[1]==KONDO_T_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;
case 't':
*offset=KONDO_T_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;
case 't':
offset[term]=KONDO_T_OFFSET;
break;
// switch term
case '.':
term=1-term;
break;
default:
// char to int
*index=*ptr-'0';
}
}
*offset1=offset[0];
*offset2=offset[1];
// if no A's or B's, then index=0
if((offset[0]==KONDO_H_OFFSET || offset[0]==KONDO_T_OFFSET) && (offset[1]==KONDO_H_OFFSET || offset[1]==KONDO_T_OFFSET)){
*index=0;
}
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;
case 't':
offset=KONDO_T_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 or t
if(offset==KONDO_H_OFFSET || offset==KONDO_T_OFFSET){
return(10*(10*offset+dim));
}
else{
return(100*(10*offset+dim)+index);
}
}