OpenFOAM中的tmp类

    技术2025-05-13  53

    在查看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>转换为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

    Processed: 0.011, SQL: 9