Click here to Skip to main content
13,771,999 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

4.6K views
6 bookmarked
Posted 12 Aug 2018
Licenced CPOL

Delphi and C# Engineering Frameworks

, 12 Aug 2018
Rate this:
Please Sign up or sign in to vote.
The article describes how math and engineering problems can be solved using Delphi and C# Analytics & Physics framework.

Introduction

Working as a software developer for math and physics applications, I have got some experience of creating engineering frameworks. The Analytics & Physics library is one of the engineering frameworks and it is intended to work with symbolic math expressions and units of measurement (http://sergey-l-gladkiy.narod.ru/index/analytics/0-13, http://sergey-l-gladkiy.narod.ru/index/physics/0-14). It was first created for one project of geophysics data processing which required converting units of measurement and implementing ‘engineering calculator’ for math operations with borehole 1D and 2D data. The first version of the library had been created using C# language. Then the framework became a separate commercial project, it was translated into Delphi and Java languages. The Delphi version has been commercialized by TMS Software (https://www.tmssoftware.com/site/tmsanalytics.asp).

From that time, the Delphi and C# versions have been developing together. Now the frameworks allow solving wide range of math, numerical and engineering problems: converting units of measurement, including nonlinear and decibels; evaluating complicated analytical expressions; symbolic derivative calculation; numerical solution of nonlinear equations systems; linear and nonlinear least squares approximation of multidimensional data; solving systems of ordinary differential equations systems and many other. The article describes how these math and engineering problems can be solved using Delphi and C# versions of the Analytics & Physics framework.

Background

Delphi and C# versions of the Analytics & Physics library provide public API (interface) for solving engineering problems. This interface realized with some main classes. The main class for analytical and symbolic calculations is Translator (Delphi classes have additional ‘T’ prefix to follow common notations). Working with units of measurement often requires string conversion, which implemented with the UnitConverter class. Here is the example code for creating instances of the classes:

var
  translator: TTranslator;
  converter: TUnitConverter;
…
  translator:= TTranslator.Create;
  converter:= TUnitConverter.Create;
 …
Translator translator = new Translator();
UnitConverter converter = new UnitConverter();

In all the code below, we suppose that an instance of the class has been created and is accessible when required.

Symbolic Manipulations and Expression Evaluations

One of amazing features of the frameworks is symbolic derivative calculation. This means that having some analytical math expression, including functions, variables and operations, we can get symbolic expression for its derivative. Here is the code for common symbolic derivative calculation:

var
  f, df: string;
begin
  f:= '√(x^3+1)-A*|x^2-1|';
  try
    if translator.CheckSyntax(f) then
    begin
      df:= translator.Derivative(f,'x');
      // using symbolic derivative df…
    end;
  except
    on ex: Exception do
    begin
      // process symbolic exception ex…
    end;
  end;
end;
string f = "√(x^3+1)-A*|x^2-1|";

try
{
    if (translator.CheckSyntax(f))
    {
        string df = translator.Derivative(f, "x");

        // using symbolic derivative df…
    }
}
catch (Exception ex)
{
    // process symbolic exception ex…
}

As can be seen from the examples, the task of symbolic derivative evaluation solved with equivalent code (in the sense of syntactic constructions): calling method ‘CheckSyntax’ for verifying formula; calling method ‘Derivative’ for the evaluation and using ‘try’ block for handling exceptions. The code is rather simple and straightforward. For a given math expression, we get the following symbolic derivative: ‘3/2/√(x^3+1)*x^2-A*sgn(x^2-1)*2*x’. It should be noted here, that the ‘Derivative’ method automatically simplifies result derivative expression to present it in simpler form.

Another main functionality of the Analytics & Physics framework is to evaluate complicated symbolic expressions, containing variables, operators and functions. That is, if we have math expression, for an example f=‘(e^x+e^-x)/2+A*B^x, we can calculate its value taking into account values of the variables. The feature of the library is that it deals with data of any type. Many libraries, that intended to evaluate math expression, bounds variables and the result of evaluation by real values. But the Analytics & Physics framework uses one universal algorithm for evaluating expressions, containing data of any type. The algorithm controls the types and compatibility of intermediate evaluation results and automatically finds operations for types of processing data. The evaluation realized with ‘Calculate’ method of the ‘Translator’ class:

function Calculate(const value: string): TValue;
public object Calculate(string value)

The C# version returns result of ‘object’ type, so, it is suitable for evaluating formula with any data. The actual type of the result can be defined via reflection mechanisms. The Delphi version uses the ‘TValue’ type from RTTI unit and this type also allows storing data of any type and recognize the actual type of the stored value.

Thus, we can evaluate formula with any return type and manipulate with the result values using similar code. Here is an example of such evaluation:

var
  f: string;
  v: TValue;
  x: TFloat;
  z: TComplex;
begin
  f:= '2*x^2-7*x+4';
  v:= translator.Calculate(f);
  x:= v.AsType<TFloat>();
  f:= '2*x^2-(7+2I)*x+4';
  v:= translator.Calculate(f);
  z:= v.AsType<TComplex>();
  // using x and z values
end;
string f = "2*x^2-7*x+4";
object v = translator.Calculate(f);
double x = (double) v;
f = "2*x^2-(7+2I)*x+4";
v = translator.Calculate(f);
Complex z = (Complex) v;
// using x and z values

The example evaluates two formulae, containing real variable ‘x’ and operations with it. Both formula are evaluated with one function ‘Calculate’, but the return results have different types, because of literal constant ‘7+2I’ in the second expression. This constant is of Complex type (Re=7, Im=2), so adding real and complex, resultant value is complex.

Analytics & Physics framework supports basic algebraic operations (addition, subtraction, multiplication, division, power), elementary (sin, cos, log, …) and special (Legendre, Bessel, Error, Gamma) functions with real and complex data. There are also realized linear algebra operations with real and complex vectors and matrices, statistical data analysis functions and many other. The library also provides the simplest mechanism for adding various operations for any external types without modifying code of core algorithms. This mechanism will be presented later in the article.

Units of Measurement and Conversions

Another task, often appearing in engineering applications, is using units of measurement and converting values from one to other units. Analytics & Physics framework provides one universal algorithm for dealing with any units of measurement, including nonlinear units and decibels. Common algorithm for conversion problem is presented with the code below:

var
  s1, s2: string;
  u1, u2: TUnit;
  v1, v2: TFloat;
  err, e1, e2: string;
  r: boolean;
begin
  s1:= 'kg/m s^2';
  s2:= 'N/ft^2';
  v1:= 1.0;
  u1:=nil;
  u2:=nil;
  try
    try
      u1:= converter.ConvertString(s1, e1);
      u2:= converter.ConvertString(s2, e2);
      r:= (e1='') and (e2='') and TUnit.Convertible(u1,u2);
      if r then
      begin
        v2:= TUnit.Convert(u1, u2, v1);
        // using v2 value
      end
      else
      begin
        // processing conversion errors e1 and e2 ...
      end;
    except
      on E: Exception do
        begin
          // processing unit conversion exception
        end;
    end;
  finally
    FreeAndNil(u1);
    FreeAndNil(u2);
  end;
end;
string us1 = "kg/m s^2";
string us2 = "N/ft^2";
double v1 = 1.0;

try
{
    Unit u1 = converter.ConvertString(us1);
    Unit u2 = converter.ConvertString(us2);

    if (Unit.Convertible(u1, u1))
    {
        double v2 = Unit.Convert(u1, u2, v1);

          // using v2 value...
    }
}
catch (Exception ex)
{
    // processing unit conversion exception
}

In the example above, we have two units of measurement ‘u1’ and ‘u2’ for measuring pressure (or mechanical stress) values. They are created by converting string representations using ‘ConvertString’ method of the ‘Converter’ class. Then they checked for dimensions compatibility with the ‘Convertible’ method of the ‘Unit’ class and if they are compatible, we use the ‘Convert’ method to get ‘v2’ value. This algorithm can be used for converting any units of measurement. The frameworks support more than 100 units of measurement for about 70 physical quantities. The units can be combined using standard rules for unit multiplication, division and power (http://en.wikipedia.org/wiki/Unit_of_measurement).

Extending Functionality of the Frameworks

As was stated above, the Analytics & Physics framework was designed to work with data of any type and it provides simple mechanisms for extending its capabilities: introducing new units of measurement; providing operators and functions for external, user defined types; realizing symbolic derivatives for new functions. Let us consider an example of operator overloading for some user defined type.

First, we need to create our specific type. Suppose we need vectors in 3D space. The types could be like the following:

TVector3D = packed record
public
  X1, X2, X3: TFloat;
  constructor Create(const x1,x2,x3: TFloat); overload;
  class operator Add(const v1, v2: TVector3D): TVector3D;
  class operator Subtract(const v1, v2: TVector3D): TVector3D;
  class operator Negative(const v: TVector3D): TVector3D;
  class operator Multiply(const v1: TVector3D; const v2: TFloat): TVector3D;
  class operator Divide(const v1: TVector3D; const v2: TFloat): TVector3D;
  …
end;
public struct Vector3D
{
    public double X1;
    public double X2;
    public double X3;
    public Vector3D(double x1, double x2, double x3) {...}
    public static Vector3D operator +(Vector3D v1, Vector3D v2) {...}
    public static Vector3D operator -(Vector3D v1, Vector3D v2) {...}
    public static Vector3D operator -(Vector3D v) {...}
    public static Vector3D operator *(double v1, Vector3D v2) {...}
    public static Vector3D operator /(Vector3D v1, double v2) {...}
    ...
}

Our goal is making possible using data of ‘Vector3D’ in math expression and evaluating them. For this purpose, we must ‘overload operators’ in the framework environment. This is implemented with simple and straightforward approach: for overloading an operation (operator or function), new class must be implemented. Here is the example of ‘+’ operator overloading:

type
  TVector3DAdd = class sealed (TGenericAddOperator<TVector3D,TVector3D,TVector3D>)
  protected
    function TypedOperation(const operand1: TVector3D; const operand2: TVector3D): TVector3D; override;
  public
    class function IsRealized: boolean; override;
  end;
…
class function TVector3DAdd.IsRealized: boolean;
begin
  result:= true;
end;

function TVector3DAdd.TypedOperation(const operand1, operand2: TVector3D): TVector3D;
begin
  result:= operand1 + operand2;
end;
public sealed class VectorAdd : GenericAddOperator<Vector3D, Vector3D, Vector3D>
{
    protected override Vector3D TypedOperation(Vector3D operand1, Vector3D operand2)
    {
        return operand1+operand2;
    }
}

The classes for overloading the addition operation inherited from the ‘GenericAddOperator’ class. Specified generic parameters defining that the first and the second operands of the addition operation are 3D vectors and the result of the operation is also vector. The overridden ‘TypedOperation’ method realizes the operation itself.

As the class for the operator realized, it will be automatically found via reflection and RTTI mechanisms and used when required. So, now we can use ‘+’ operation for 3D vector data. Analogously, all other operations can be realized. Here is an example of evaluating math expressions, containing 3D vector data:

var
  translator: TTranslator;
  v: TVariable;
  f: string;
  r: TValue;
begin
  v:= TObjectVariable.Create('V', TValue.From(TVector3D.Create(1,-1,2)), TypeInfo(TVector3D));
  translator.Add(v);
  v:= TObjectVariable.Create('D', TValue.From(TVector3D.Create(0.5, 0.3,-0.7)), TypeInfo(TVector3D));
  translator.Add(v);

  f:= 'V*sin(Pi/4)-D/2';
  r:= translator.Calculate(f);
  // using result r value...
end;
Variable v = new ObjectVariable("V", new Vector3D(1, -1, 2), typeof(Vector3D));
translator.Add(v);
v = new ObjectVariable("D", new Vector3D(0.5, 0.3, -0.7), typeof(Vector3D));
translator.Add(v);

string f = "V*sin(Pi/4)-D/2";
object r = translator.Calculate(f);
// using result r value...

In the example code above, we created variables ‘V’ and ‘D’ to store vector data and added them to the ‘translator’ instance. The used type ‘ObjectVariable’ can store data of any type (‘Vector3D’ in the case). After the variable has been added, it can be used in math expressions. Evaluating given vector expression ‘V*sin(Pi/4)-D/2’ for current variable values, we get the following result ‘r = (0.457106781186547 -0.857106781186547 1.7642135623731)’. The variable values can be changed via special interface of the ‘Translator’ class, so we can calculate various expressions for different variable values.

It should be noted that the Analytics & Physics framework supports ‘implicit operator overloading’. It means that if some type has overloaded math operators, they can be automatically used for implementing corresponding operations with data for evaluating analytical expressions. Thus, for the case of the ‘Vector3D’ class, there is no need to write new classes for common algebraic operators.

Combining Numerical Methods with Symbolic Capabilities

Many of engineering problems can be stated in analytical form as a set of math expressions and formulae. But rarely, they can be solved in analytical form too. Most often, complicated engineering problems are solved using numerical methods. Analytics & Physics framework includes many numerical tools for solving various math and engineering problems: numerical integration, approximation, solving nonlinear equations, solving initial value problems for ordinary differential equations and other. The feature of the framework is that all numerical tools are totally incorporated with the symbolic capabilities.

As an example, let us consider a problem of integration of univariate function on some interval. The problem can be solved with the following code:

var
  f: string;
  x1, x2, ivalue: TFloat;
  n: integer;
  sf1D: TSymbolicFunction1D;
  integrator: TIntegrator1DClass;
begin
  f:= 'sin(x)*e^(x^2/8)';  // Integrable function.
  x1:= 0.0; // Left value of the integration interval.
  x2:= 3.0; // Right value of the integration interval.
  n:= 10;   // Number of integration nodes.

  // Select one of the integrator classes.
  integrator:= TGauss2NodeIntegrator;
  try
    // Symbolic function instance for integration.
    sf1D:= TSymbolicFunction1D.Create('x', f);
    // Integrate the function with the integrator.
    ivalue:= integrator.Integral(sf1D.F, x1, x2, n);
    // use the integral value 'ivalue'...
  finally
    FreeAndNil(sf1D);
  end;
end;
string f = "sin(x)*e^(x^2/8)"; // Integrable function.
double x1 = 0.0; // Left value of the integration interval.
double x2 = 3.0; // Right value of the integration interval.
int n = 10;      // Number of integration nodes.

// Use one of the integrators.
Integrator1D integrator = new Gauss2NodeIntegrator();
// Symbolic function instance for integration.
SymbolicFunction1D sf1D = new SymbolicFunction1D("x", f);
// Integrate the function with the integrator.
double ivalue = integrator.Integral(sf1D.F, x1, x2, n);
// use the integral value 'ivalue'...

In the code above, integrand function ‘f’ presented in symbolic form as math expression. Such representations has many advantages, because there is no need to create special delegate methods for the numerical integration algorithm, as it is required in almost all numerical libraries. The delegate created automatically by the math expression. The symbolic data can be easily transfer through networks, stored with standard serialization algorithms and shown to the user with the appropriate form as a formula.

Conclusions

This article introduced engineering framework Analytics & Physics. There are two versions of the framework – for Delphi native applications and C# version for .NET. The framework allows converting units of measurement, including nonlinear and decibels, evaluating complicated analytical expressions, symbolic derivative calculation and numerical solution of math and engineering problems. The framework’s capabilities can be extended without modifying core algorithms. The extensions can be made by introducing new units of measurement, defining operations for external, user defined types and adding symbolic derivatives for new functions. The symbolic capabilities of the framework are totally incorporated with many numerical algorithms for solving various math and engineering problems. Demo versions of the framework with example source code applications can be found here:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sergey L. Gladkiy
Team Leader
Russian Federation Russian Federation
EDUCATION:

Master’s degree in Mechanics.

PhD degree in Mathematics and Physics.



PROFESSIONAL EXPERIENCE:

Ten years’ experience in developing scientific programs (C#, Delphi, Java, C++, Fortran).



SCIENTIFIC INTERESTS:

Mathematical modeling, analytical calculations, numerical methods, boundary value problems, 3D geometry modeling, artificial intelligence.

You may also be interested in...

Comments and Discussions

 
PraiseGreat job. Pin
spi14-Aug-18 2:41
memberspi14-Aug-18 2:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.181119.1 | Last Updated 13 Aug 2018
Article Copyright 2018 by Sergey L. Gladkiy
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid