//****************************************************************************** //Name: GetInterpTensor * // * //Purpose: get the interpolated tensor at an arbitrary position * // * //Takes: pointer to the position as packed in a tensor * //****************************************************************************** tensor field::GetInterpTensor(tensor &pos) { double position[3]; tensor ret_val; for(int i = 0; i < 3; i++) position[i] = pos.Val(i); ret_val <= GetInterpTensor(position); return ret_val; }
//****************************************************************************** //Name: SetTensor * // * //Purpose: Set the tensor portion of the field * // * //Takes: takes a position in tensor form and the address of the tensor * //****************************************************************************** void field::SetTensor(const tensor &pos, const tensor &rval) { int i; double position[3]; for( i = 0; i < 3; i++) position[i] = pos.Val(i); SetTensor(position, rval); }
//****************************************************************************** //Name: SetTensor * // * //Purpose: Set the tensor portion of the field * // * //Takes: takes a pointer to a position array and the address of the tensor * //****************************************************************************** void field::SetTensor(int *indices, const tensor &rval) { int *index; int *r_index; int i, j, temp; double value; //Error check if( rval.p->num_indices != (p->num_indices - 3) ) error("SetTensor error:","cannot assign the tensor to a field point"); for(i = 3; i < p->num_indices; i++) { if( rval.p->range[i-3] != p->range[i] ) error("SetTensor error:","cannot assign the tensor to a field point"); } //set up the index array that indexes into the field and set the specified position index = new int[p->num_indices]; for( i = 0; i < 3; i++) index[i] = indices[i]; //set up the index array that indexes into the rval tensor r_index = new int[rval.p->num_indices]; //set the field for(i = 0; i < rval.p->product; i++) { //pack the r_index array (see tensor::Contract) temp = 0; for(j = 0; j < rval.p->num_indices - 1; j++) { r_index[j] = (i - i%rval.p->scales[j] - temp)/rval.p->scales[j]; temp += r_index[j] * rval.p->scales[j]; } r_index[j] = (i - temp)/rval.p->scales[j]; //complete the index array with the tensor indices for(j = 3; j < p->num_indices; j++) index[j] = r_index[j - 3]; value = rval.Val(r_index); //put the rval tensors value into the field at specified position Set(value,index); } //Clean up delete [] index; delete [] r_index; }
//****************************************************************************** //Name: GetTensor * // * //Purpose: get the tensor portion of the field given the position * // * //Takes: position stored as a tensor * //****************************************************************************** tensor field::GetTensor(const tensor &pos) { int i; double position[3]; tensor temp; for( i = 0; i < 3; i++ ) position[i] = pos.Val(i); temp <= GetTensor(position); return temp; }
//****************************************************************************** //Name: Contract * // * //Purpose: Form the contraction of the two specified tensors on the selected * // indices * // * //Takes: the of the rval tensor * //****************************************************************************** tensor tensor::Contract(tensor const &B, int ind1, int ind2) const { int i, counter, r_counter; int tot_indices; int *range; //Error check the indices and make sure neither is out of range if( ind1 >= p->num_indices ) error("Contraction error:","LVAL index out of range"); if( ind2 >= B.p->num_indices ) error("Contraction error:","RVAL index out of range"); if( p->range[ind1] != B.p->range[ind2] ) error("Contraction error:","contracted indices must have the same range"); //Determine the total number of indices on the new tensor tot_indices = p->num_indices + B.p->num_indices - 2; //Allocate space for temporary range if( tot_indices == 0 ) { range = new int[1]; } else { range = new int[tot_indices]; } r_counter = 0; //Pack the range array appropriately counter = 0; for( i = 0; i < p->num_indices; i++) { if(counter != ind1) { range[r_counter] = p->range[i]; r_counter++; } counter++; } counter = 0; //note that tot_indices + 2 is needed to loop over all the appropriate ranges for( i = p->num_indices; i < tot_indices + 2; i++) { if(counter != ind2) { range[r_counter] = B.p->range[i - p->num_indices]; r_counter++; } counter++; } //create a temp tensor and handle scalar result tensor con; if( tot_indices == 0 ) { tot_indices = 1; range[0] = 1; } con.Resize0(tot_indices, range); delete [] range; //Now comes the fun part int *index, *B_index, *con_index; int j; double contract; int temp; //Allocate index arrays to hold the current index structure index = new int[p->num_indices]; B_index = new int[B.p->num_indices]; con_index = new int[con.p->num_indices]; for(i = 0; i < con.p->product; i++) { //pack the con_index array temp = 0; for(j = 0; j < con.p->num_indices - 1; j++) { con_index[j] = (i - i%con.p->scales[j] - temp)/con.p->scales[j]; temp += con_index[j] * con.p->scales[j]; } con_index[j] = (i - temp)/con.p->scales[j]; //form the index structure for the LVAL object counter = 0; r_counter = 0; for( j = 0; j < p->num_indices; j++) { if(counter != ind1) { index[j] = con_index[r_counter]; r_counter++; } counter++; } //form the index structure for the RVAL object counter = 0; for( j = 0; j < B.p->num_indices; j++) { if(counter != ind2) { B_index[j] = con_index[r_counter]; r_counter++; } counter++; } //form the contraction contract = 0; for( j = 0; j < p->range[ind1]; j++) { index[ind1] = j; B_index[ind2] = j; contract += Val(index)*B.Val(B_index); } con.p->m[i] = contract; } //clean up delete [] index; delete [] B_index; delete [] con_index; //return the result return con; }