Page 1 of 1

ListGetElement operations

Posted: 08 Mar 2018, 18:36
by raback
Hi All,

Elmer has historically had the feature that any parameter is fetched directly from the list using its name. There can be a large number of different types in the list allowing any keyword to have a value given in a multitude of different ways. Be it constant, table, MATC function or a subroutine. Now this has also a handicap: retrieving the list has a cost which may be particularly high if we are retrieving the same constant for every integration point.

To speed up things there (and hopefully make them at least as pretty) there are since quite a while element-wise operations that can be used instead of the old list operations. All the new operations need a handle which includes information that helps to save some time. One first initializes the keyword for correct section type (string) and then inside the element loop may call more economically the value for the keyword:

Code: Select all

SUBROUTINE ListInitElementKeyword( Handle,Section,Name,minv,maxv)
And within the loop for Element the values are obtained using the following functions

Code: Select all

FUNCTION ListGetElementReal( Handle, Basis, Element, Found ) RESULT( Rvalue ) 
FUNCTION ListGetElementLogical( Handle, Element, Found ) RESULT(Lvalue) 
FUNCTION ListGetElementInteger( Handle, Element, Found ) RESULT(Ivalue) 
FUNCTION ListGetElementString( Handle, Element, Found ) RESULT( CValue )
The old counterpart of these comes without the "Element" definition.

The most speedy practices of Elmer currently employ vectorization strategies. For that there is also a vectorized version of the GetReal function which returns the values at all Gaussian integration point. It combines optimally with the GetElementInfoVec routine.

Code: Select all

FUNCTION ListGetElementRealVec( Handle, ngp, BasisVec, Element,Found ) RESULT( Rvalues ) 
The speed of the new practices for obtaining constant value, or a value depending on global variables (such as time) may be even 10-fold. The way to save time is basically that the handle knows whether we have constants globally, or at least within a list. For functional dependency there is not much difference but luckily often the coefficient are constants. The routines are also more versatile than the simple GetReal command in that there is no changes in the code needed to make the functional evaluations directly at the integration points. Only "Keyword At Ip = Logical True" is needed to change the behavior.

The string case was more difficult to get any speed-up. Even if the string is constant the operation of fetching and comparing a string takes time. For that there is a special function that compares string to some reference. It is much faster and would be the choice if there are only a few possible cases the string can take:

Code: Select all

FUNCTION ListCompareElementString( Handle, CValue2, Element, Found ) RESULT( SameString )
There are a few test cases related to these List operations:

Code: Select all

KeywordCompare: Logical, Integer, String
KeywordCompare2: Different cases for getting Real
KeywordCompare3: Different cases for getting RealVec (utilizes also ElementInfoVec)
ModelPDEevol: Multithreaded, vectorized ModelPDE utlizing the new keyword convention
In each case (except the last one) we have a synthetic loop over elements and the results are summed up. These should be the same (except for "At Ip" routines which do not have an old counterpart). Also each case has timings for getting the keywords.