/// <summary> /// /// </summary> /// <param name="value"></param> /// <returns></returns> public override QsValue DifferentiateOperation(QsValue vl) { QsValue value; if (vl is QsReference) { value = ((QsReference)vl).ContentValue; } else { value = vl; } if (value is QsScalar) { var t = new QsTensor(); foreach (var m in t.MatrixLayers) { t.AddMatrix((QsMatrix)m.DifferentiateOperation(value)); } return(t); } else { return(base.DifferentiateOperation(value)); } }
/// <summary> /// The function receive rows from vectors or matrices or may be tensors /// </summary> /// <param name="values">Vectors</param> /// <returns></returns> public static QsValue MatrixFromValues(params QsValue[] values) { if (values[0] is QsTensor) { if (values.Count() == 1) { return(values[0]); } // treat the case of tensors QsTensor tensor = new QsTensor(); foreach (var tn in values) { if (tn.GetType() != typeof(QsTensor)) { throw new QsException("Non Tensor in a matrix of tensors is not valid expression."); } else { tensor.AddInnerTensor((QsTensor)tn); } } return(tensor); } QsMatrix mat = new QsMatrix(); foreach (var val in values) { if (val is QsVector) { mat.AddVector((QsVector)val); } else if (val is QsMatrix) { foreach (var vc in ((QsMatrix)val)) { mat.AddVector((QsVector)vc); } } else { throw new QsInvalidOperationException("Value to be added is not a vector nor a matrix."); } } return(mat); }
/// <summary> /// /// </summary> /// <param name="values">Matrices or Tensors</param> /// <returns></returns> public static QsValue TensorFromValues(params QsValue[] values) { QsTensor tens = new QsTensor(); foreach (var val in values) { if (val is QsMatrix) { tens.AddMatrix((QsMatrix)val); } else if (val is QsTensor) { tens.AddInnerTensor((QsTensor)val); } else { throw new QsException("Component is not a matrix value."); } } return(tens); }
/// <summary> /// Create A matrix from a row values by aligning values to the left in /// </summary> /// <param name="values"></param> /// <returns></returns> public static QsValue MatrixRowFromValues(params QsValue[] values) { // what about [g g] and g is tensor // in this case return value should be tensor // from the higher degree of above g if (values[0] is QsTensor) { if (values.Count() == 1) { return(values[0]); } // in rare cases or event known cases by me Ahmed Sadek and because of parsing // sometimes I enclose tensor variable inside matrix [g g <|4 3|> ] // so in this case i will the return as it is. QsTensor tensor = new QsTensor(); foreach (var inTensor in values) { if (inTensor.GetType() != typeof(QsTensor)) { throw new QsException("Non Tensor in a matrix of tensors is not valid expression."); } else { tensor.AddInnerTensor((QsTensor)inTensor); } } return(tensor); } QsMatrix m = new QsMatrix(); foreach (var v in values) { if (v is QsScalar) { if (m.RowsCount == 0) { m.AddVector((QsVector)VectorFromValues(v)); } else { m.Rows[0].AddComponent((QsScalar)v); } } if (v is QsVector) { if (m.RowsCount == 0) { m.AddVector(((QsVector)v).Clone() as QsVector); } else if (m.RowsCount == 1) { m.Rows[0].AddComponents((QsVector)v); } else { throw new QsInvalidOperationException("Couldn't adding vector to multi row matrix"); } } if (v is QsMatrix) { if (m.RowsCount == 0) { m = null; m = QsMatrix.CopyMatrix((QsMatrix)v); } else if (m.RowsCount == ((QsMatrix)v).RowsCount) { foreach (var col in ((QsMatrix)v).Columns) { m.AddColumnVector(col); } } else { throw new QsInvalidOperationException("Couldn't adding different row matrices"); } } } return(m); }
public override QsValue SubtractOperation(QsValue vl) { QsValue value; if (vl is QsReference) { value = ((QsReference)vl).ContentValue; } else { value = vl; } if (value is QsScalar) { var scalar = value as QsScalar; QsTensor NewTensor = new QsTensor(); if (this.Order > 3) { foreach (var iTensor in this.InnerTensors) { NewTensor.SubtractOperation((QsTensor)iTensor.AddOperation(value)); } } else { for (int il = 0; il < this.MatrixLayers.Count; il++) { QsMatrix ResultMatrix = (QsMatrix)this.MatrixLayers[il].SubtractOperation(scalar); NewTensor.AddMatrix(ResultMatrix); } } return(NewTensor); } if (value is QsTensor) { var tensor = value as QsTensor; if (this.Order != (tensor.Order)) { throw new QsException("Adding two different ranked tensors are not supported"); } if (this.Order > 3) { QsTensor NewTensor = new QsTensor(); for (int i = 0; i < this.InnerTensors.Count(); i++) { var iTensor = this.InnerTensors[i]; NewTensor.AddInnerTensor((QsTensor) iTensor.SubtractOperation(tensor.InnerTensors[i])); } return(NewTensor); } else { if (tensor.MatrixLayers.Count == this.MatrixLayers.Count) { // the operation will succeed if (tensor.FaceRowsCount == this.FaceRowsCount) { if (tensor.FaceColumnsCount == this.FaceColumnsCount) { QsTensor NewTensor = new QsTensor(); for (int il = 0; il < this.MatrixLayers.Count; il++) { QsMatrix ResultMatrix = (QsMatrix)this.MatrixLayers[il].SubtractOperation(tensor.MatrixLayers[il]); NewTensor.AddMatrix(ResultMatrix); } return(NewTensor); } } } } } throw new QsException("Tensor Subtract Operation with " + value.GetType().Name + " Failed"); }
public override QsValue GetIndexedItem(QsParameter[] allIndices) { int[] indices = new int[allIndices.Length]; for (int ix = 0; ix < indices.Length; ix++) { indices[ix] = (int)((QsScalar)allIndices[ix].QsNativeValue).NumericalQuantity.Value; } int dr = this.Order - indices.Count(); if (dr < 0) { throw new QsException("Indices count exceed the tensor rank, only specify indices to the same rank to get scalar, or less to get vectors to tensors"); } else if (dr == 0) { return(GetScalar(indices)); } else if (dr == 1) { // return vector if (this.Order == 2) { return(this[0][indices[0]]); } else if (this.Order == 3) { return(this[indices[0]][indices[1]]); } else { QsTensor t = this; int ix = 0; int ic = indices.Count(); while (ix < ic - 2) { int idx = indices[ix]; if (idx < 0) { idx = t.InnerTensors.Count + idx; } t = t.InnerTensors[idx]; ix++; } return(t[indices[ix]][indices[ix + 1]]); //ix was increased the latest time. } } else if (dr == 2) { // return matrix; if (this.Order == 2) { return(this[indices[0]]); } else { // specify the tensor QsTensor t = this; int ix = 0; int ic = indices.Count(); while (ix < ic - 1) { int idx = indices[ix]; if (idx < 0) { idx = t.InnerTensors.Count + idx; } t = t.InnerTensors[idx]; ix++; } // then return the matrix. return(t[indices[ix]]); //ix was increased the latest time. } } else { // return tensor QsTensor t = this; int ix = 0; while (ix < indices.Count()) { int idx = indices[ix]; if (idx < 0) { idx = t.InnerTensors.Count + idx; } t = t.InnerTensors[idx]; ix++; } return(t); } }
public override QsValue DotProductOperation(QsValue vl) { QsValue value; if (vl is QsReference) { value = ((QsReference)vl).ContentValue; } else { value = vl; } QsTensor tensor; if (value is QsTensor) { tensor = (QsTensor)value; } else if (value is QsMatrix) { tensor = new QsTensor((QsMatrix)value); } else if (value is QsVector) { tensor = new QsTensor(new QsMatrix((QsVector)value)); } else if (value is QsScalar) { tensor = new QsTensor(new QsMatrix(new QsVector((QsScalar)value))); } else { throw new QsException("Tensor Operation with non mathematical type is not permitted"); } if (tensor == null) { throw new QsException("Must be a tensor for scalar product"); } if (this.Order > 3) { throw new NotImplementedException(); } else if (this.Order == 1) { if (tensor.Order == 1) { var thisVec = this[0][0]; var thatVec = tensor[0][0]; var result = (QsScalar)thisVec.DotProductOperation(thatVec); return(new QsTensor(new QsMatrix(new QsVector(result)))); } } else if (this.Order == 2) { // only for tensors that looks like matrix. // reference: http://people.rit.edu/pnveme/EMEM851n/constitutive/tensors_rect.html // the scalar product called there as double dot ':' and I don't know if this is right or wrong // /* * * if (tensor.Order == 2) * { * var matrix = tensor.MatrixLayers[0]; * var thisMatrix = this.MatrixLayers[0]; * if (thisMatrix.RowsCount == matrix.RowsCount && thisMatrix.ColumnsCount == matrix.ColumnsCount) * { * QsScalar Total = default(QsScalar); * * for (int i = 0; i < thisMatrix.RowsCount; i++) * { * for (int j = 0; j < thisMatrix.ColumnsCount; j++) * { * if (Total == null) Total = thisMatrix[i, j] * matrix[j, i]; * else Total = Total + thisMatrix[i, j] * matrix[j, i]; * } * } * return Total; * } * else * { * throw new QsException("The two matrices should be equal in rows and columns"); * } * } */ } throw new NotImplementedException(); }
public override QsValue MultiplyOperation(QsValue vl) { QsValue value; if (vl is QsReference) { value = ((QsReference)vl).ContentValue; } else { value = vl; } if (value is QsScalar) { var scalar = (QsScalar)value; QsTensor NewTensor = new QsTensor(); if (this.Order > 3) { foreach (var iTensor in this.InnerTensors) { NewTensor.AddInnerTensor((QsTensor)iTensor.MultiplyOperation(value)); } } else { for (int il = 0; il < this.MatrixLayers.Count; il++) { QsMatrix ResultMatrix = (QsMatrix)this.MatrixLayers[il].MultiplyOperation(scalar); NewTensor.AddMatrix(ResultMatrix); } } return(NewTensor); } if (value is QsTensor) { var tensor = (QsTensor)value; if (this.Order == 1 && tensor.Order == 1) { var thisVec = this[0][0]; var thatVec = tensor[0][0]; var result = (QsMatrix)thisVec.TensorProductOperation(thatVec); return(new QsTensor(result)); } if (this.Order == 2 && tensor.Order <= 2) { //tenosrial product of two matrices will result in another matrix also. QsMatrix result = (QsMatrix)this.MatrixLayers[0].TensorProductOperation(tensor.MatrixLayers[0]); return(new QsTensor(result)); } else { throw new QsException("", new NotImplementedException()); } } throw new QsException("Tensor Multiplication Operation with " + value.GetType().Name + " Failed"); }
/// <summary> /// Initiate adding tensor in current tensor /// and increase the rank of the tensor /// most probably inserting tensor as a sub tensor will increase rank starting from 4th rank. /// </summary> /// <param name="qsTensor"></param> public void AddInnerTensor(QsTensor qsTensor) { if (qsTensor.Order == 0) { if (MatrixLayers.Count == 0) { var matrix = new QsMatrix(new QsVector(qsTensor.MatrixLayers[0][0, 0])); MatrixLayers.Add(matrix); } else { // successive insertion of zero rank tensor will be put into the vecor in the matrix in the tensor. MatrixLayers[0].Rows[0].AddComponent(qsTensor.MatrixLayers[0][0, 0]); } } else if (qsTensor.Order == 1) { if (MatrixLayers.Count == 0) { var matrix = new QsMatrix(qsTensor.MatrixLayers[0].Rows[0]); MatrixLayers.Add(matrix); } else { // successive insertion of first rank tensor insert them in the matrix. var v = qsTensor.MatrixLayers[0].Rows[0]; if (MatrixLayers.Count > 0) { if (v.Count != this.FaceColumnsCount) { throw new QsInvalidInputException("Adding first rank tensor with different number of columns"); } } MatrixLayers[0].AddVector(v); } } else if (qsTensor.Order == 2) { var matrix = QsMatrix.CopyMatrix(qsTensor.MatrixLayers[0]); if (MatrixLayers.Count > 0) { if (matrix.RowsCount == this.FaceRowsCount) { if (matrix.ColumnsCount == this.FaceColumnsCount) { } else { throw new QsInvalidOperationException("Adding Second Rank tensor with different number of columns"); } } else { throw new QsInvalidOperationException("Adding Second Rank tensor with different number of rows"); } } MatrixLayers.Add(matrix); } else { // Third rank tensor or more if (InnerTensors == null) { InnerTensors = new List <QsTensor>(); } InnerTensors.Add(qsTensor); } }