OpenFOAM中的tmp类

在查看interFoam 求解器代码过程中,在alphaEqn.H头文件中发现了如下命令:

 tmp<fv::ddtScheme<scalar>> ddtAlpha
    (
        fv::ddtScheme<scalar>::New
        (
            mesh,
            mesh.ddtScheme("ddt(alpha)")
        )
    );

这里,我们对其中的tmp做具体探讨。

1.介绍

tmp是一个包装类,它允许从functions / methods方法返回本地对象,而无需复制。它还允许程序快速清除内存中的对象,这可以用来减少峰值内存。tmp在后台工作,通常在顶层代码中不可见。

它并不是必须的,但可以减少程序运行过程中的工作量并提高程序的效率。

在OpenFOAM中,我们一般用它来处理场量数据(场量存储数据一般很大,传统的数据传递方式浪费内存资源,甚至超出允许范围)。我们可以在返回场量对象时显式地使用它。此外,tmp可以应用于算法中间,删除场量空间,以减少峰值内存。

单个字段以上的所有对象都可以使用tmp。它们都可以从tmp转换为object。要使用tmp返回操作对象,只需将返回类型用tmp<>括起来:

2.代码分析

 //原始数据
xxxField myFunc ()
    {
        xxxField returnMe(new xxxField);
        // 返回局部变量
        return returnMe;
    } 
// 处理后
tmp<xxxField> myFunc()
    {
        tmp<xxxField> tReturnMe(new xxxField);
        xxxField& returnMe = tReturnMe();//()表示引用
        // 返回局部变量
        return tReturnMe;
    }

清除场量所占用的空间,需在tmp中应用discardable data

tmp<xxxField> discardableDataObject;

或者

discardableDataObject.clear();

可以查看tmpI.H里面的代码,里面有关于clear()函数的声明。求解器里面也有类似的使用,如:UEqn.clear();

3.总结

(该部分翻译自http://openfoamwiki.net/index.php/OpenFOAM_guide/tmp)

正常情况下,编译器要先调用复制构造函数,创建复制的返回文件,然后再调用析构函数清除原来的对象。而tmp对象取代了这个两个步骤,当编译器调用复制构造函数时,tmp仅仅复制指针和引用,而数据原封不动,当编译器调用析构函数时,tmp将他的指针重定向到NULL。因为数据有了一个新的引用,编译器也就不管他了,数据也就保留了下来。

重写复制构造函数和析构函数不足以使tmp工作。如果tmp要透明,它的行为必须与展开对象的正常行为相同。这意味着有时需要正确地删除tmp,或者需要正确地复制tmp的数据。这意味着它需要被检测,判断它是一个临时的局部对象,或是一个重复的对象,还是堆栈上的常规对象。为此:

tmp持有一个标志来确定它是否是临时对象。

  • 如果tmp是由指向对象的指针构造的,则该标志为true,就像使用new关键字一样。
  • 如果tmp是由引用构造的,则标志设置为false,如果对象已经存在,或者tmp被推送到堆 栈上,就会发生这种情况。
  • 有关适用于指针的类似包装类,请参见autoPtr。这一部分可参考苏老师的博客

tmp所指向的对象需要实时跟踪有多少引用指向它们。

  • 这是通过refCount类实现的,也是实现tmp的高速缓存之一。

当被删除时,tmp询问它的对象有多少引用指向它。

  • 如果有多个指针,tmp会在删除时重定向其指针。
  • 如果只有一个指针,tmp不会重定向指针,数据最终会被删除。

参考文献:
[1.]:http://openfoamwiki.net/index.php/OpenFOAM_guide/tmp
[2]:http://blog.sina.com.cn/s/blog_5fdfa7e60100rdb3.html

你可能感兴趣的:(代码编程,cfd,OpenFOAM)