Please ensure Javascript is enabled for purposes of website accessibility
Powered by Zoomin Software. For more details please contactZoomin

AVEVA Pipeline Operations for Liquids

Create a class that implements the interface

  • Last UpdatedApr 24, 2025
  • 3 minute read

You can create multiple plugins, each one corresponding to their own class that implements the interface. The class must be public so it can be discovered and used externally.

Note: Multiple product groups can map to the same plugin.

For a sample implementation, refer to the following ExamplePlugin class:

Sample: ExamplePlugin Class

using OASySDNA.LMS.VolumeCorrection.Plugins;

using System;

namespace OASySDNA.LMS.SDKTests.RealTime.Common.VolumeCorrectionPluginExample

{

/// <summary>

/// To create a Volume Correction Plugin create a public class that implements

/// <see cref="IVolumeCorrectionPlugin"/>

///

/// The units of the input and outputs are configured on the product group

/// </summary>

public sealed class ExamplePlugin : IVolumeCorrectionPlugin

{

// Pressure constants for calculating density. This is only an example of how you can create your own variable and arrays to be used in the calculations as needed.

public double[] CorrectionTable = new double[4]

{

-0.004594649,

0.006123243,

-3.17075E-05,

5.48397E-05

};

public CustomCorrectionFactors CalculateCustomFactors<TArgs>(in TArgs args) where TArgs : ICalculateCustomFactorsArgs

{

var customFactors = CustomCorrectionFactors.Create();

double hydroC = 1 - 0.00023 * (args.Temperature - 20.0) - 0.000002 * (args.Temperature - 20.0);

// Adding the custom factor in this case "Hydrometer Corrections" available for subsequent methods

// on volume corrections

customFactors.AddFactor(GetCorrectionFactorName(args.SourceType), hydroC);

return customFactors;

}

/// <summary>

/// Implemented here to illustrate

/// which tables the custom correction factors

/// will end up on.

/// </summary>

/// <param name="source">The source of the calculations</param>

/// <returns>the field we are putting the custom correction factor on</returns>

private string GetCorrectionFactorName(SourceType source)

{

switch (source)

{

case SourceType.Tank:

return "hydroCTank";

case SourceType.Linepack:

return "hydroCPipelineSegment";

case SourceType.VirtualFlowComputer:

return "hydroCAccumulator";

default:

return String.Empty;

}

}

public double CalculateCorrectedDensity<TArgs>(in TArgs args) where TArgs : ICalculateCorrectedDensityArgs

{

// you can use contants to calculate corrected density

var numerator = (args.UncorrectedDensity

- CorrectionTable[0]

*(args.Temperature - 20.0)

- CorrectionTable[2]

* Math.Pow((args.Temperature - 20.0), 2.0));

var denominator = (1.0

+ CorrectionTable[1]

* (args.Temperature - 20.0)

+ CorrectionTable[3]

* Math.Pow((args.Temperature - 20.0), 2.0));

// here we are using a custom factor defined in the method CalculateCustomFactors

// the custom factor will only exist for one VolumeCorrection.

// i.e. one Krunch Cycle for Tank, Accumulator or Linepack and needs to be added each

// time the class is called

return (numerator / denominator)*args.GetCustomFactor(GetCorrectionFactorName(args.SourceType));

}

public double CalculateGrossStandardVolume<TArgs>(in TArgs args) where TArgs : ICalculateGrossStandardVolumeArgs

{

return args.GrossObservedVolume * args.TemperatureCorrectionFactor * args.PressureCorrectionFactor;

}

public double CalculateTemperatureCorrectionFactor<TArgs>(in TArgs args) where TArgs : ICalculateTemperatureCorrectionFactorArgs

{

return 1.0 - 0.00109 * (args.Temperature - 20.0);

}

public double CalculatePressureCorrectionFactor<TArgs>(in TArgs args) where TArgs : ICalculatePressureCorrectionFactorArgs

{

var absPressure = Math.Abs(args.Pressure);

return (absPressure - 1.0) / absPressure;

}

/// <summary>

/// Shows an example of the BaseDentisy, assuming API corrections of 2004.

/// </summary>

/// <returns></returns>

public double BaseDensityOfWater()

{

return 999.016;

}

}

}

Combining Baseline and Custom Corrections

You have the flexibility to combine baseline volume corrections (API 2004, API 1980 and Reference Fluid Thermodynamic and Transport Properties (REFPROP) Mass and Volume) with custom corrections if there is a reason to do so. For example, your plugin can provide custom density corrections and then use API 1980 to calculate the Gross Standard Volume (GSV).

To use the standard volume correction libraries within a class implementing IVolumeCorrectionPlugin, instantiate a class with the name XCorrections (where X is the name of the correction). For example, to use API 2004 to calculate corrected density, simply instantiate API2004Corrections as shown in the following example:

{

/// <summary>

/// An API2004Corrections should be instantiated once in the

/// constructor of the plugin

/// </summary>

private readonly API2004Corrections api2004Corrections;

public Example2004Plugin()

{

api2004Corrections = new API2004Corrections();

}

public double BaseDensityOfWater()

{

return api2004Corrections.BaseDensityOfWater();

}

public double CalculateCorrectedDensity<TArgs>(in TArgs args) where TArgs :

ICalculateCorrectedDensityArgs

{

return api2004Corrections.CalculateCorrectedDensity(args);

}

To use the REFPROP Mass correction for GSV, the volume must be re-interpreted as a mass. AVEVA Pipeline Operations for Liquids automatically adjusts for mass as long as the plugin implements IVolumeCorrectionAsMassPlugin, as shown in the following example:

{

public class ExampleRefPropMassPlugin : IVolumeAsMassCorrectionPlugin

{

private readonly RefpropMassCorrections corrections;

public ExampleRefPropMassPlugin()

{

corrections = new RefpropMassCorrections();

}

public double BaseDensityOfWater()

{

return corrections.BaseDensityOfWater();

}

public double CalculateCorrectedDensity<TArgs>(in TArgs args)

where TArgs : ICalculateCorrectedDensityArgs

{

return corrections.CalculateCorrectedDensity(args);

}

public CustomCorrectionFactors CalculateCustomFactors<TArgs>(in TArgs args)

where TArgs : ICalculateCustomFactorsArgs

{

return corrections.CalculateCustomFactors(args);

}

public double CalculateGrossStandardVolume<TArgs>(in TArgs args)

where TArgs : ICalculateGrossStandardVolumeArgs

{

return corrections.CalculateGrossStandardVolume(args);

}

Exception Handling

If a plugin is implemented with custom corrections for which one of Tank, VFC, or Linepack is not supported, simply detect the source and initiate an exception as shown in the following example:

public double CalculateGrossStandardVolume<TArgs>(in TArgs args) where TArgs :

ICalculateGrossStandardVolumeArgs

{

if(args.SourceType == SourceType.VirtualFlowComputer)

{

throw new System.Exception("VFC not supported");

}

return corrections.CalculateGrossStandardVolume(args);

}