openFOAM-paraview-catalyst (#10129)
* paraview: adding variants to use external packages as internal do not compile * paraview: add latest paraview version * catalyst: fixed libvtkexpat undefined reference linking error in Catalyst 5.5 * catalyst: add latest catalyst version * catalyst: added ParaView_DIR env variable to catalyst module * add paraview, catalyst patches - https://gitlab.kitware.com/vtk/vtk-m/merge_requests/1166 - https://gitlab.kitware.com/paraview/paraview/merge_requests/2433 - https://gitlab.kitware.com/paraview/paraview/merge_requests/2436 * - Handle updated library paths for catalyst. Versions 5.4 and old places libraries under a paraview subdirectory. Eg, "lib/paraview-5.4", they are now placed directly under "lib" - Minor code style cleanup * Handle update library and python paths for ParaView-5.5 * catalyst: added ParaView_DIR path to spack_env * BUG: applied the patch to the extracted catalyst source files * paraview: added missing self to a member variable * paraview: added Paraview_DIR to env * catalyst: added osmesa variant * of-catalyst: added new package * add (FOAM,WM)_PROJECT_DIR also to spack_env environment * depends on first openfoam release supporting catalyst * openfoam-com: added missing env variables to module generation * openfoam: fixed flake8 errors * of-catalyst: added full variant and openfoam version dependency * paraview: adding variants to use external packages as internal do not compile * catalyst: fixed libvtkexpat undefined reference linking error in Catalyst 5.5 * catalyst: added ParaView_DIR env variable to catalyst module * add paraview, catalyst patches - https://gitlab.kitware.com/vtk/vtk-m/merge_requests/1166 - https://gitlab.kitware.com/paraview/paraview/merge_requests/2433 - https://gitlab.kitware.com/paraview/paraview/merge_requests/2436 * - Handle updated library paths for catalyst. Versions 5.4 and old places libraries under a paraview subdirectory. Eg, "lib/paraview-5.4", they are now placed directly under "lib" - Minor code style cleanup * Handle update library and python paths for ParaView-5.5 * catalyst: added ParaView_DIR path to spack_env * BUG: applied the patch to the extracted catalyst source files * of-catalyst: added new package * add (FOAM,WM)_PROJECT_DIR also to spack_env environment * depends on first openfoam release supporting catalyst * paraview: added missing self to a member variable * openfoam-com: added missing env variables to module generation * openfoam: fixed flake8 errors * paraview: added Paraview_DIR to env * catalyst: added osmesa variant * of-catalyst: added full variant and openfoam version dependency * paraview-catalyst: use always external expat and netcdf * of-catalyst: reformatted package description * paraview-catalyst: removed duplicated function * catalyst: fixed flake8 error * of-catalyst: fixed license header * of-catalyst: minor changes * of-catalyst: renamed gitrepo with git * of-catalyst: removed useless gitrepo parameter
This commit is contained in:

committed by
Adam J. Stewart

parent
bdc9804078
commit
e7e32cc2d6
@@ -7,6 +7,7 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
from spack.patch import absolute_path_for_package
|
||||||
|
|
||||||
|
|
||||||
class Catalyst(CMakePackage):
|
class Catalyst(CMakePackage):
|
||||||
@@ -33,17 +34,31 @@ class Catalyst(CMakePackage):
|
|||||||
variant('python', default=False, description='Enable Python support')
|
variant('python', default=False, description='Enable Python support')
|
||||||
variant('essentials', default=False, description='Enable Essentials support')
|
variant('essentials', default=False, description='Enable Essentials support')
|
||||||
variant('extras', default=False, description='Enable Extras support')
|
variant('extras', default=False, description='Enable Extras support')
|
||||||
variant('rendering', default=False, description='Enable Vtk Rendering support')
|
variant('rendering', default=False, description='Enable VTK Rendering support')
|
||||||
|
variant('osmesa', default=True, description='Use offscreen rendering')
|
||||||
|
|
||||||
depends_on('git')
|
depends_on('git', type='build')
|
||||||
depends_on('mpi')
|
depends_on('mpi')
|
||||||
depends_on('python@2:2.8', when='+python', type=("build", "link", "run"))
|
depends_on('python@2:2.8', when='+python', type=("build", "link", "run"))
|
||||||
depends_on('python', when='~python', type=("build"))
|
depends_on('python', when='~python', type=("build"))
|
||||||
depends_on('mesa', when='+rendering')
|
depends_on('mesa', when='+rendering')
|
||||||
depends_on("libx11", when='+rendering')
|
depends_on('libx11', when='+rendering')
|
||||||
depends_on("libxt", when='+rendering')
|
depends_on('libxt', when='+rendering')
|
||||||
depends_on('cmake@3.3:', type='build')
|
depends_on('cmake@3.3:', type='build')
|
||||||
|
|
||||||
|
@when('@5.5.0:5.5.2')
|
||||||
|
def patch(self):
|
||||||
|
"""Apply the patch (it should be fixed in Paraview 5.6)
|
||||||
|
at the package dir to the source code in
|
||||||
|
root_cmakelists_dir."""
|
||||||
|
patch_name = 'vtkm-catalyst-pv551.patch'
|
||||||
|
pkg_dir = os.path.dirname(absolute_path_for_package(self))
|
||||||
|
patch = which("patch", required=True)
|
||||||
|
with working_dir(self.root_cmakelists_dir):
|
||||||
|
patch('-s', '-p', '1', '-i',
|
||||||
|
join_path(pkg_dir, patch_name),
|
||||||
|
"-d", '.')
|
||||||
|
|
||||||
def url_for_version(self, version):
|
def url_for_version(self, version):
|
||||||
"""Handle ParaView version-based custom URLs."""
|
"""Handle ParaView version-based custom URLs."""
|
||||||
if version < Version('5.1.0'):
|
if version < Version('5.1.0'):
|
||||||
@@ -53,6 +68,30 @@ def url_for_version(self, version):
|
|||||||
else:
|
else:
|
||||||
return self._urlfmt_xz.format(version.up_to(2), version, '')
|
return self._urlfmt_xz.format(version.up_to(2), version, '')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def paraview_subdir(self):
|
||||||
|
"""The paraview subdirectory name as paraview-major.minor"""
|
||||||
|
return 'paraview-{0}'.format(self.spec.version.up_to(2))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def editions(self):
|
||||||
|
"""Transcribe spack variants into names of Catalyst Editions"""
|
||||||
|
selected = ['Base'] # Always required
|
||||||
|
|
||||||
|
if '+python' in self.spec:
|
||||||
|
selected.append('Enable-Python')
|
||||||
|
|
||||||
|
if '+essentials' in self.spec:
|
||||||
|
selected.append('Essentials')
|
||||||
|
|
||||||
|
if '+extras' in self.spec:
|
||||||
|
selected.append('Extras')
|
||||||
|
|
||||||
|
if '+rendering' in self.spec:
|
||||||
|
selected.append('Rendering-Base')
|
||||||
|
|
||||||
|
return selected
|
||||||
|
|
||||||
def do_stage(self, mirror_only=False):
|
def do_stage(self, mirror_only=False):
|
||||||
"""Unpacks and expands the fetched tarball.
|
"""Unpacks and expands the fetched tarball.
|
||||||
Then, generate the catalyst source files."""
|
Then, generate the catalyst source files."""
|
||||||
@@ -62,38 +101,15 @@ def do_stage(self, mirror_only=False):
|
|||||||
paraview_dir = os.path.join(self.stage.path,
|
paraview_dir = os.path.join(self.stage.path,
|
||||||
'ParaView-v' + str(self.version))
|
'ParaView-v' + str(self.version))
|
||||||
catalyst_script = os.path.join(paraview_dir, 'Catalyst', 'catalyze.py')
|
catalyst_script = os.path.join(paraview_dir, 'Catalyst', 'catalyze.py')
|
||||||
|
editions_dir = os.path.join(paraview_dir, 'Catalyst', 'Editions')
|
||||||
catalyst_source_dir = os.path.abspath(self.root_cmakelists_dir)
|
catalyst_source_dir = os.path.abspath(self.root_cmakelists_dir)
|
||||||
|
|
||||||
command = ['python', catalyst_script,
|
command = ['python', catalyst_script,
|
||||||
'-r', paraview_dir]
|
'-r', paraview_dir,
|
||||||
|
'-o', catalyst_source_dir]
|
||||||
|
|
||||||
catalyst_edition = os.path.join(paraview_dir, 'Catalyst',
|
for edition in self.editions:
|
||||||
'Editions', 'Base')
|
command.extend(['-i', os.path.join(editions_dir, edition)])
|
||||||
command.append('-i')
|
|
||||||
command.append(catalyst_edition)
|
|
||||||
if '+python' in self.spec:
|
|
||||||
catalyst_edition = os.path.join(paraview_dir, 'Catalyst',
|
|
||||||
'Editions', 'Enable-Python')
|
|
||||||
command.append('-i')
|
|
||||||
command.append(catalyst_edition)
|
|
||||||
if '+essentials' in self.spec:
|
|
||||||
catalyst_edition = os.path.join(paraview_dir, 'Catalyst',
|
|
||||||
'Editions', 'Essentials')
|
|
||||||
command.append('-i')
|
|
||||||
command.append(catalyst_edition)
|
|
||||||
if '+extras' in self.spec:
|
|
||||||
catalyst_edition = os.path.join(paraview_dir, 'Catalyst',
|
|
||||||
'Editions', 'Extras')
|
|
||||||
command.append('-i')
|
|
||||||
command.append(catalyst_edition)
|
|
||||||
if '+rendering' in self.spec:
|
|
||||||
catalyst_edition = os.path.join(paraview_dir, 'Catalyst',
|
|
||||||
'Editions', 'Rendering-Base')
|
|
||||||
command.append('-i')
|
|
||||||
command.append(catalyst_edition)
|
|
||||||
|
|
||||||
command.append('-o')
|
|
||||||
command.append(catalyst_source_dir)
|
|
||||||
|
|
||||||
if not os.path.isdir(catalyst_source_dir):
|
if not os.path.isdir(catalyst_source_dir):
|
||||||
os.mkdir(catalyst_source_dir)
|
os.mkdir(catalyst_source_dir)
|
||||||
@@ -104,15 +120,29 @@ def do_stage(self, mirror_only=False):
|
|||||||
self.stage.path))
|
self.stage.path))
|
||||||
|
|
||||||
def setup_environment(self, spack_env, run_env):
|
def setup_environment(self, spack_env, run_env):
|
||||||
|
# paraview 5.5 and later
|
||||||
|
# - cmake under lib/cmake/paraview-5.5
|
||||||
|
# - libs under lib
|
||||||
|
# - python bits under lib/python2.8/site-packages
|
||||||
if os.path.isdir(self.prefix.lib64):
|
if os.path.isdir(self.prefix.lib64):
|
||||||
lib_dir = self.prefix.lib64
|
lib_dir = self.prefix.lib64
|
||||||
else:
|
else:
|
||||||
lib_dir = self.prefix.lib
|
lib_dir = self.prefix.lib
|
||||||
paraview_version = 'paraview-%s' % self.spec.version.up_to(2)
|
|
||||||
run_env.prepend_path('LIBRARY_PATH', join_path(lib_dir,
|
if self.spec.version <= Version('5.4.1'):
|
||||||
paraview_version))
|
lib_dir = join_path(lib_dir, paraview_subdir)
|
||||||
run_env.prepend_path('LD_LIBRARY_PATH', join_path(lib_dir,
|
run_env.set('ParaView_DIR', self.prefix)
|
||||||
paraview_version))
|
run_env.prepend_path('LIBRARY_PATH', lib_dir)
|
||||||
|
run_env.prepend_path('LD_LIBRARY_PATH', lib_dir)
|
||||||
|
|
||||||
|
if '+python' in self.spec:
|
||||||
|
python_version = self.spec['python'].version.up_to(2)
|
||||||
|
run_env.prepend_path('PYTHONPATH', join_path(lib_dir,
|
||||||
|
'python{0}'.format(python_version),
|
||||||
|
'site-packages'))
|
||||||
|
|
||||||
|
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
|
||||||
|
spack_env.set('ParaView_DIR', self.prefix)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root_cmakelists_dir(self):
|
def root_cmakelists_dir(self):
|
||||||
@@ -136,8 +166,24 @@ def build_directory(self):
|
|||||||
|
|
||||||
def cmake_args(self):
|
def cmake_args(self):
|
||||||
"""Populate cmake arguments for Catalyst."""
|
"""Populate cmake arguments for Catalyst."""
|
||||||
|
spec = self.spec
|
||||||
|
|
||||||
|
def variant_bool(feature, on='ON', off='OFF'):
|
||||||
|
"""Ternary for spec variant to ON/OFF string"""
|
||||||
|
if feature in spec:
|
||||||
|
return on
|
||||||
|
return off
|
||||||
|
|
||||||
|
def nvariant_bool(feature):
|
||||||
|
"""Negated ternary for spec variant to OFF/ON string"""
|
||||||
|
return variant_bool(feature, on='OFF', off='ON')
|
||||||
|
|
||||||
cmake_args = [
|
cmake_args = [
|
||||||
'-DPARAVIEW_GIT_DESCRIBE=v%s' % str(self.version)
|
'-DPARAVIEW_GIT_DESCRIBE=v%s' % str(self.version),
|
||||||
|
'-DVTK_USE_SYSTEM_EXPAT:BOOL=ON',
|
||||||
|
'-DVTK_USE_X:BOOL=%s' % nvariant_bool('+osmesa'),
|
||||||
|
'-DVTK_USE_OFFSCREEN:BOOL=%s' % variant_bool('+osmesa'),
|
||||||
|
'-DVTK_OPENGL_HAS_OSMESA:BOOL=%s' % variant_bool('+osmesa')
|
||||||
]
|
]
|
||||||
return cmake_args
|
return cmake_args
|
||||||
|
|
||||||
|
@@ -0,0 +1,487 @@
|
|||||||
|
# The catalyst changes (the working directory for output) are slated for
|
||||||
|
# paraview-5.6.
|
||||||
|
# They are API-compatible with paraview-5.5 but not ABI compatible.
|
||||||
|
#
|
||||||
|
# https://gitlab.kitware.com/paraview/paraview/merge_requests/2433
|
||||||
|
# https://gitlab.kitware.com/paraview/paraview/merge_requests/2436
|
||||||
|
#
|
||||||
|
--- Catalyst-v5.5.0/CoProcessing/Catalyst/vtkCPProcessor.cxx.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ Catalyst-v5.5.0/CoProcessing/Catalyst/vtkCPProcessor.cxx 2018-05-11 12:02:26.894772713 +0200
|
||||||
|
@@ -38,6 +38,7 @@
|
||||||
|
#include "vtkStringArray.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
+#include <vtksys/SystemTools.hxx>
|
||||||
|
|
||||||
|
struct vtkCPProcessorInternals
|
||||||
|
{
|
||||||
|
@@ -47,12 +48,13 @@
|
||||||
|
};
|
||||||
|
|
||||||
|
vtkStandardNewMacro(vtkCPProcessor);
|
||||||
|
-vtkMultiProcessController* vtkCPProcessor::Controller = NULL;
|
||||||
|
+vtkMultiProcessController* vtkCPProcessor::Controller = nullptr;
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
vtkCPProcessor::vtkCPProcessor()
|
||||||
|
{
|
||||||
|
this->Internal = new vtkCPProcessorInternals;
|
||||||
|
- this->InitializationHelper = NULL;
|
||||||
|
+ this->InitializationHelper = nullptr;
|
||||||
|
+ this->WorkingDirectory = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
@@ -61,14 +63,15 @@
|
||||||
|
if (this->Internal)
|
||||||
|
{
|
||||||
|
delete this->Internal;
|
||||||
|
- this->Internal = NULL;
|
||||||
|
+ this->Internal = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->InitializationHelper)
|
||||||
|
{
|
||||||
|
this->InitializationHelper->Delete();
|
||||||
|
- this->InitializationHelper = NULL;
|
||||||
|
+ this->InitializationHelper = nullptr;
|
||||||
|
}
|
||||||
|
+ this->SetWorkingDirectory(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
@@ -95,7 +98,7 @@
|
||||||
|
{
|
||||||
|
if (which < 0 || which >= this->GetNumberOfPipelines())
|
||||||
|
{
|
||||||
|
- return NULL;
|
||||||
|
+ return nullptr;
|
||||||
|
}
|
||||||
|
int counter = 0;
|
||||||
|
vtkCPProcessorInternals::PipelineListIterator iter = this->Internal->Pipelines.begin();
|
||||||
|
@@ -108,7 +111,7 @@
|
||||||
|
counter++;
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
- return NULL;
|
||||||
|
+ return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
@@ -130,17 +133,41 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
-int vtkCPProcessor::Initialize()
|
||||||
|
+int vtkCPProcessor::Initialize(const char* workingDirectory)
|
||||||
|
{
|
||||||
|
- if (this->InitializationHelper == NULL)
|
||||||
|
+ if (this->InitializationHelper == nullptr)
|
||||||
|
{
|
||||||
|
this->InitializationHelper = this->NewInitializationHelper();
|
||||||
|
}
|
||||||
|
+ // make sure the directory exists here so that we only do it once
|
||||||
|
+ if (workingDirectory)
|
||||||
|
+ {
|
||||||
|
+ vtkMultiProcessController* controller = vtkMultiProcessController::GetGlobalController();
|
||||||
|
+ int success = 1;
|
||||||
|
+ if (controller == nullptr || controller->GetLocalProcessId() == 0)
|
||||||
|
+ {
|
||||||
|
+ success = vtksys::SystemTools::MakeDirectory(workingDirectory) == true ? 1 : 0;
|
||||||
|
+ if (success == 0)
|
||||||
|
+ {
|
||||||
|
+ vtkWarningMacro("Could not make "
|
||||||
|
+ << workingDirectory << " directory. "
|
||||||
|
+ << "Results will be generated in current working directory instead.");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (controller)
|
||||||
|
+ {
|
||||||
|
+ controller->Broadcast(&success, 1, 0);
|
||||||
|
+ }
|
||||||
|
+ if (success)
|
||||||
|
+ {
|
||||||
|
+ this->SetWorkingDirectory(workingDirectory);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
-int vtkCPProcessor::Initialize(vtkMPICommunicatorOpaqueComm& comm)
|
||||||
|
+int vtkCPProcessor::Initialize(vtkMPICommunicatorOpaqueComm& comm, const char* workingDirectory)
|
||||||
|
{
|
||||||
|
#ifdef PARAVIEW_USE_MPI
|
||||||
|
if (vtkCPProcessor::Controller)
|
||||||
|
@@ -148,7 +175,7 @@
|
||||||
|
vtkErrorMacro("Can only initialize with a communicator once per process.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
- if (this->InitializationHelper == NULL)
|
||||||
|
+ if (this->InitializationHelper == nullptr)
|
||||||
|
{
|
||||||
|
vtkMPICommunicator* communicator = vtkMPICommunicator::New();
|
||||||
|
communicator->InitializeExternal(&comm);
|
||||||
|
@@ -157,12 +184,12 @@
|
||||||
|
this->Controller = controller;
|
||||||
|
this->Controller->SetGlobalController(controller);
|
||||||
|
communicator->Delete();
|
||||||
|
- return this->Initialize();
|
||||||
|
+ return this->Initialize(workingDirectory);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
static_cast<void>(&comm); // get rid of variable not used warning
|
||||||
|
- return this->Initialize();
|
||||||
|
+ return this->Initialize(workingDirectory);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -225,6 +252,13 @@
|
||||||
|
input->GetFieldData()->AddArray(catalystChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ std::string originalWorkingDirectory;
|
||||||
|
+ if (this->WorkingDirectory)
|
||||||
|
+ {
|
||||||
|
+ originalWorkingDirectory = vtksys::SystemTools::GetCurrentWorkingDirectory();
|
||||||
|
+ vtksys::SystemTools::ChangeDirectory(this->WorkingDirectory);
|
||||||
|
+ }
|
||||||
|
for (vtkCPProcessorInternals::PipelineListIterator iter = this->Internal->Pipelines.begin();
|
||||||
|
iter != this->Internal->Pipelines.end(); iter++)
|
||||||
|
{
|
||||||
|
@@ -248,6 +282,10 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (originalWorkingDirectory.empty() == false)
|
||||||
|
+ {
|
||||||
|
+ vtksys::SystemTools::ChangeDirectory(originalWorkingDirectory);
|
||||||
|
+ }
|
||||||
|
// we want to reset everything here to make sure that new information
|
||||||
|
// is properly passed in the next time.
|
||||||
|
dataDescription->ResetAll();
|
||||||
|
@@ -259,7 +297,7 @@
|
||||||
|
{
|
||||||
|
if (this->Controller)
|
||||||
|
{
|
||||||
|
- this->Controller->SetGlobalController(NULL);
|
||||||
|
+ this->Controller->SetGlobalController(nullptr);
|
||||||
|
this->Controller->Finalize(1);
|
||||||
|
this->Controller->Delete();
|
||||||
|
}
|
||||||
|
--- Catalyst-v5.5.0/CoProcessing/Catalyst/vtkCPProcessor.h.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ Catalyst-v5.5.0/CoProcessing/Catalyst/vtkCPProcessor.h 2018-05-11 12:02:26.894772713 +0200
|
||||||
|
@@ -76,14 +76,16 @@
|
||||||
|
virtual void RemoveAllPipelines();
|
||||||
|
|
||||||
|
/// Initialize the co-processor. Returns 1 if successful and 0
|
||||||
|
- /// otherwise.
|
||||||
|
/// otherwise. If Catalyst is built with MPI then Initialize()
|
||||||
|
/// can also be called with a specific MPI communicator if
|
||||||
|
/// MPI_COMM_WORLD isn't the proper one. Catalyst is initialized
|
||||||
|
- /// to use MPI_COMM_WORLD by default.
|
||||||
|
- virtual int Initialize();
|
||||||
|
+ /// to use MPI_COMM_WORLD by default. Both methods have an optional
|
||||||
|
+ /// workingDirectory argument which will set *WorkingDirectory* so
|
||||||
|
+ /// that files will be put relative to this directory.
|
||||||
|
+ virtual int Initialize(const char* workingDirectory = nullptr);
|
||||||
|
#ifndef __WRAP__
|
||||||
|
- virtual int Initialize(vtkMPICommunicatorOpaqueComm& comm);
|
||||||
|
+ virtual int Initialize(
|
||||||
|
+ vtkMPICommunicatorOpaqueComm& comm, const char* workingDirectory = nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// The Catalyst input field data string array name. This array will
|
||||||
|
@@ -111,6 +113,13 @@
|
||||||
|
/// implementation an opportunity to clean up, before it is destroyed.
|
||||||
|
virtual int Finalize();
|
||||||
|
|
||||||
|
+ /// Get the current working directory for outputting Catalyst files.
|
||||||
|
+ /// If not set then Catalyst output files will be relative to the
|
||||||
|
+ /// current working directory. This will not affect where Catalyst
|
||||||
|
+ /// looks for Python scripts. *WorkingDirectory* gets set through
|
||||||
|
+ /// the *Initialize()* methods.
|
||||||
|
+ vtkGetStringMacro(WorkingDirectory);
|
||||||
|
+
|
||||||
|
protected:
|
||||||
|
vtkCPProcessor();
|
||||||
|
virtual ~vtkCPProcessor();
|
||||||
|
@@ -118,6 +127,11 @@
|
||||||
|
/// Create a new instance of the InitializationHelper.
|
||||||
|
virtual vtkObject* NewInitializationHelper();
|
||||||
|
|
||||||
|
+ /// Set the current working directory for outputting Catalyst files.
|
||||||
|
+ /// This is a protected method since simulation code adaptors should
|
||||||
|
+ /// set this through the *Initialize()* methods.
|
||||||
|
+ vtkSetStringMacro(WorkingDirectory);
|
||||||
|
+
|
||||||
|
private:
|
||||||
|
vtkCPProcessor(const vtkCPProcessor&) = delete;
|
||||||
|
void operator=(const vtkCPProcessor&) = delete;
|
||||||
|
@@ -125,6 +139,7 @@
|
||||||
|
vtkCPProcessorInternals* Internal;
|
||||||
|
vtkObject* InitializationHelper;
|
||||||
|
static vtkMultiProcessController* Controller;
|
||||||
|
+ char* WorkingDirectory;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
--- Catalyst-v5.5.0/CoProcessing/Catalyst/vtkCPXMLPWriterPipeline.cxx.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ Catalyst-v5.5.0/CoProcessing/Catalyst/vtkCPXMLPWriterPipeline.cxx 2018-05-11 12:02:26.894772713 +0200
|
||||||
|
@@ -31,6 +31,7 @@
|
||||||
|
#include <vtkSmartPointer.h>
|
||||||
|
#include <vtkUnstructuredGrid.h>
|
||||||
|
|
||||||
|
+#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
@@ -174,7 +175,7 @@
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < dataDescription->GetNumberOfInputDescriptions(); i++)
|
||||||
|
{
|
||||||
|
- const char* inputName = dataDescription->GetInputDescriptionName(i);
|
||||||
|
+ std::string inputName = dataDescription->GetInputDescriptionName(i);
|
||||||
|
vtkCPInputDataDescription* idd = dataDescription->GetInputDescription(i);
|
||||||
|
vtkDataObject* grid = idd->GetGrid();
|
||||||
|
if (grid == nullptr)
|
||||||
|
@@ -206,6 +207,8 @@
|
||||||
|
vtkSMStringVectorProperty* fileName =
|
||||||
|
vtkSMStringVectorProperty::SafeDownCast(writer->GetProperty("FileName"));
|
||||||
|
|
||||||
|
+ // If we have a / in the channel name we take it out of the filename we're going to write to
|
||||||
|
+ inputName.erase(std::remove(inputName.begin(), inputName.end(), '/'), inputName.end());
|
||||||
|
std::ostringstream o;
|
||||||
|
if (this->Path.empty() == false)
|
||||||
|
{
|
||||||
|
--- Catalyst-v5.5.0/Wrapping/Python/paraview/coprocessing.py.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ Catalyst-v5.5.0/Wrapping/Python/paraview/coprocessing.py 2018-05-11 12:02:27.038772408 +0200
|
||||||
|
@@ -11,22 +11,12 @@
|
||||||
|
from paraview.vtk.vtkPVVTKExtensionsCore import *
|
||||||
|
import math
|
||||||
|
|
||||||
|
-# -----------------------------------------------------------------------------
|
||||||
|
-def IsInModulo(timestep, frequencyArray):
|
||||||
|
- """
|
||||||
|
- Return True if the given timestep is in one of the provided frequency.
|
||||||
|
- This can be interpreted as follow::
|
||||||
|
-
|
||||||
|
- isFM = IsInModulo(timestep, [2,3,7])
|
||||||
|
-
|
||||||
|
- is similar to::
|
||||||
|
+# If the user created a filename in a location that doesn't exist by default we'll
|
||||||
|
+# make the directory for them. This can be changed though by setting createDirectoriesIfNeeded
|
||||||
|
+# to False.
|
||||||
|
+createDirectoriesIfNeeded = True
|
||||||
|
|
||||||
|
- isFM = (timestep % 2 == 0) or (timestep % 3 == 0) or (timestep % 7 == 0)
|
||||||
|
- """
|
||||||
|
- for frequency in frequencyArray:
|
||||||
|
- if frequency > 0 and (timestep % frequency == 0):
|
||||||
|
- return True
|
||||||
|
- return False
|
||||||
|
+# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class CoProcessor(object):
|
||||||
|
"""Base class for co-processing Pipelines.
|
||||||
|
@@ -68,6 +58,9 @@
|
||||||
|
self.__CinemaTracks = {}
|
||||||
|
self.__InitialFrequencies = {}
|
||||||
|
self.__PrintEnsightFormatString = False
|
||||||
|
+ self.__TimeStepToStartOutputAt=0
|
||||||
|
+ self.__ForceOutputAtFirstCall=False
|
||||||
|
+ self.__FirstTimeStepIndex = None
|
||||||
|
|
||||||
|
def SetPrintEnsightFormatString(self, enable):
|
||||||
|
"""If outputting ExodusII files with the purpose of reading them into
|
||||||
|
@@ -87,6 +80,17 @@
|
||||||
|
"Incorrect argument type: %s, must be a dict" % type(frequencies))
|
||||||
|
self.__InitialFrequencies = frequencies
|
||||||
|
|
||||||
|
+ def SetInitialOutputOptions(self, timeStepToStartOutputAt, forceOutputAtFirstCall):
|
||||||
|
+ """Set the frequencies at which the pipeline needs to be updated.
|
||||||
|
+ Typically, this is called by the subclass once it has determined what
|
||||||
|
+ timesteps co-processing will be needed to be done.
|
||||||
|
+ frequencies is a map, with key->string name of for the simulation
|
||||||
|
+ input, and value is a list of frequencies.
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ self.__TimeStepToStartOutputAt=timeStepToStartOutputAt
|
||||||
|
+ self.__ForceOutputAtFirstCall=forceOutputAtFirstCall
|
||||||
|
+
|
||||||
|
def EnableLiveVisualization(self, enable, frequency = 1):
|
||||||
|
"""Call this method to enable live-visualization. When enabled,
|
||||||
|
DoLiveVisualization() will communicate with ParaView server if possible
|
||||||
|
@@ -115,7 +119,7 @@
|
||||||
|
# if this is a time step to do live then all of the inputs
|
||||||
|
# must be made available. note that we want the pipeline built
|
||||||
|
# before we do the actual first live connection.
|
||||||
|
- if self.__EnableLiveVisualization and timestep % self.__LiveVisualizationFrequency == 0 \
|
||||||
|
+ if self.__EnableLiveVisualization and self.NeedToOutput(timestep, self.__LiveVisualizationFrequency) \
|
||||||
|
and self.__LiveVisualizationLink:
|
||||||
|
if self.__LiveVisualizationLink.Initialize(servermanager.ActiveConnection.Session.GetSessionProxyManager()):
|
||||||
|
num_inputs = datadescription.GetNumberOfInputDescriptions()
|
||||||
|
@@ -132,13 +136,13 @@
|
||||||
|
# hasn't been set up yet). If we don't have live enabled
|
||||||
|
# we know that the output frequencies aren't changed and can
|
||||||
|
# just use the initial frequencies.
|
||||||
|
- if self.__InitialFrequencies or not self.__EnableLiveVisualization:
|
||||||
|
+ if self.__ForceOutputAtFirstCall or self.__InitialFrequencies or not self.__EnableLiveVisualization:
|
||||||
|
num_inputs = datadescription.GetNumberOfInputDescriptions()
|
||||||
|
for cc in range(num_inputs):
|
||||||
|
input_name = datadescription.GetInputDescriptionName(cc)
|
||||||
|
|
||||||
|
freqs = self.__InitialFrequencies.get(input_name, [])
|
||||||
|
- if self.__EnableLiveVisualization or ( self and IsInModulo(timestep, freqs) ):
|
||||||
|
+ if self.__EnableLiveVisualization or ( self and self.IsInModulo(timestep, freqs) ):
|
||||||
|
datadescription.GetInputDescription(cc).AllFieldsOn()
|
||||||
|
datadescription.GetInputDescription(cc).GenerateMeshOn()
|
||||||
|
else:
|
||||||
|
@@ -149,15 +153,14 @@
|
||||||
|
for writer in self.__WritersList:
|
||||||
|
frequency = writer.parameters.GetProperty(
|
||||||
|
"WriteFrequency").GetElement(0)
|
||||||
|
- if (timestep % frequency) == 0 or \
|
||||||
|
- datadescription.GetForceOutput() == True:
|
||||||
|
+ if self.NeedToOutput(timestep, frequency) or datadescription.GetForceOutput() == True:
|
||||||
|
writerinputs = cpstate.locate_simulation_inputs(writer)
|
||||||
|
for writerinput in writerinputs:
|
||||||
|
datadescription.GetInputDescriptionByName(writerinput).AllFieldsOn()
|
||||||
|
datadescription.GetInputDescriptionByName(writerinput).GenerateMeshOn()
|
||||||
|
|
||||||
|
for view in self.__ViewsList:
|
||||||
|
- if (view.cpFrequency and timestep % view.cpFrequency == 0) or \
|
||||||
|
+ if (view.cpFrequency and self.NeedToOutput(timestep, view.cpFrequency)) or \
|
||||||
|
datadescription.GetForceOutput() == True:
|
||||||
|
viewinputs = cpstate.locate_simulation_inputs_for_view(view)
|
||||||
|
for viewinput in viewinputs:
|
||||||
|
@@ -192,8 +195,7 @@
|
||||||
|
for writer in self.__WritersList:
|
||||||
|
frequency = writer.parameters.GetProperty(
|
||||||
|
"WriteFrequency").GetElement(0)
|
||||||
|
- if (timestep % frequency) == 0 or \
|
||||||
|
- datadescription.GetForceOutput() == True:
|
||||||
|
+ if self.NeedToOutput(timestep, frequency) or datadescription.GetForceOutput() == True:
|
||||||
|
fileName = writer.parameters.GetProperty("FileName").GetElement(0)
|
||||||
|
paddingamount = writer.parameters.GetProperty("PaddingAmount").GetElement(0)
|
||||||
|
helperName = writer.GetXMLName()
|
||||||
|
@@ -203,6 +205,23 @@
|
||||||
|
else:
|
||||||
|
ts = str(timestep).rjust(paddingamount, '0')
|
||||||
|
writer.FileName = fileName.replace("%t", ts)
|
||||||
|
+ if '/' in writer.FileName and createDirectoriesIfNeeded:
|
||||||
|
+ oktowrite = [1.]
|
||||||
|
+ import vtk
|
||||||
|
+ comm = vtk.vtkMultiProcessController.GetGlobalController()
|
||||||
|
+ if comm.GetLocalProcessId() == 0:
|
||||||
|
+ import os
|
||||||
|
+ newDir = writer.FileName[0:writer.FileName.rfind('/')]
|
||||||
|
+ try:
|
||||||
|
+ os.makedirs(newDir)
|
||||||
|
+ except OSError:
|
||||||
|
+ if not os.path.isdir(newDir):
|
||||||
|
+ print ("ERROR: Cannot make directory for", writer.FileName, ". No data will be written.")
|
||||||
|
+ oktowrite[0] = 0.
|
||||||
|
+ comm.Broadcast(oktowrite, 1, 0)
|
||||||
|
+ if oktowrite[0] == 0:
|
||||||
|
+ # we can't make the directory so no reason to update the pipeline
|
||||||
|
+ return
|
||||||
|
writer.UpdatePipeline(datadescription.GetTime())
|
||||||
|
|
||||||
|
def WriteImages(self, datadescription, rescale_lookuptable=False,
|
||||||
|
@@ -240,7 +259,7 @@
|
||||||
|
|
||||||
|
cinema_dirs = []
|
||||||
|
for view in self.__ViewsList:
|
||||||
|
- if (view.cpFrequency and timestep % view.cpFrequency == 0) or \
|
||||||
|
+ if (view.cpFrequency and self.NeedToOutput(timestep, view.cpFrequency)) or \
|
||||||
|
datadescription.GetForceOutput() == True:
|
||||||
|
fname = view.cpFileName
|
||||||
|
ts = str(timestep).rjust(padding_amount, '0')
|
||||||
|
@@ -267,6 +286,24 @@
|
||||||
|
if dirname:
|
||||||
|
cinema_dirs.append(dirname)
|
||||||
|
else:
|
||||||
|
+ if '/' in fname and createDirectoriesIfNeeded:
|
||||||
|
+ oktowrite = [1.]
|
||||||
|
+ import vtk
|
||||||
|
+ comm = vtk.vtkMultiProcessController.GetGlobalController()
|
||||||
|
+ if comm.GetLocalProcessId() == 0:
|
||||||
|
+ import os
|
||||||
|
+ newDir = fname[0:fname.rfind('/')]
|
||||||
|
+ try:
|
||||||
|
+ os.makedirs(newDir)
|
||||||
|
+ except OSError:
|
||||||
|
+ if not os.path.isdir(newDir):
|
||||||
|
+ print ("ERROR: Cannot make directory for", fname, ". No image will be output.")
|
||||||
|
+ oktowrite[0] = 0.
|
||||||
|
+ comm.Broadcast(oktowrite, 1, 0)
|
||||||
|
+ if oktowrite[0] == 0:
|
||||||
|
+ # we can't make the directory so no reason to update the pipeline
|
||||||
|
+ return
|
||||||
|
+
|
||||||
|
if image_quality is None and fname.endswith('png'):
|
||||||
|
# for png quality = 0 means no compression. compression can be a potentially
|
||||||
|
# very costly serial operation on process 0
|
||||||
|
@@ -307,7 +344,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
timeStep = datadescription.GetTimeStep()
|
||||||
|
- if self.__EnableLiveVisualization and timeStep % self.__LiveVisualizationFrequency == 0:
|
||||||
|
+ if self.__EnableLiveVisualization and self.NeedToOutput(timeStep, self.__LiveVisualizationFrequency):
|
||||||
|
if not self.__LiveVisualizationLink.Initialize(servermanager.ActiveConnection.Session.GetSessionProxyManager()):
|
||||||
|
return
|
||||||
|
|
||||||
|
@@ -412,7 +449,7 @@
|
||||||
|
"""
|
||||||
|
controller = servermanager.ParaViewPipelineController()
|
||||||
|
# assume that a client only proxy with the same name as a writer
|
||||||
|
- # is available in "insitu_writer_paramters"
|
||||||
|
+ # is available in "insitu_writer_parameters"
|
||||||
|
|
||||||
|
# Since coprocessor sometimes pass writer as a custom object and not
|
||||||
|
# a proxy, we need to handle that. Just creating any arbitrary writer
|
||||||
|
@@ -666,3 +703,42 @@
|
||||||
|
#restore what we showed
|
||||||
|
pv_introspect.restore_visibility(pxystate)
|
||||||
|
return os.path.basename(vfname)
|
||||||
|
+
|
||||||
|
+ def IsInModulo(self, timestep, frequencies):
|
||||||
|
+ """
|
||||||
|
+ Return True if the given timestep is in one of the provided frequency.
|
||||||
|
+ This can be interpreted as follow::
|
||||||
|
+
|
||||||
|
+ isFM = IsInModulo(timestep-timeStepToStartOutputAt, [2,3,7])
|
||||||
|
+
|
||||||
|
+ is similar to::
|
||||||
|
+
|
||||||
|
+ isFM = (timestep-timeStepToStartOutputAt % 2 == 0) or (timestep-timeStepToStartOutputAt % 3 == 0) or (timestep-timeStepToStartOutputAt % 7 == 0)
|
||||||
|
+
|
||||||
|
+ The timeStepToStartOutputAt is the first timestep that will potentially be output.
|
||||||
|
+ """
|
||||||
|
+ if timestep < self.__TimeStepToStartOutputAt and not self.__ForceOutputAtFirstCall:
|
||||||
|
+ return False
|
||||||
|
+ for frequency in frequencies:
|
||||||
|
+ if frequency > 0 and self.NeedToOutput(timestep, frequency):
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ def NeedToOutput(self, timestep, frequency):
|
||||||
|
+ """
|
||||||
|
+ Return True if we need to output based on the input timestep and frequency. Checks based
|
||||||
|
+ __FirstTimeStepIndex, __FirstTimeStepIndex, __ForceOutputAtFirstCall and __TimeStepToStartOutputAt
|
||||||
|
+ member variables.
|
||||||
|
+ """
|
||||||
|
+ if self.__FirstTimeStepIndex == None:
|
||||||
|
+ self.__FirstTimeStepIndex = timestep
|
||||||
|
+
|
||||||
|
+ if self.__ForceOutputAtFirstCall and self.__FirstTimeStepIndex == timestep:
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ if self.__TimeStepToStartOutputAt <= timestep and (timestep-self.__TimeStepToStartOutputAt) % frequency == 0:
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ return False
|
48
var/spack/repos/builtin/packages/of-catalyst/package.py
Normal file
48
var/spack/repos/builtin/packages/of-catalyst/package.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Copyright 2013-2018 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
from spack import *
|
||||||
|
|
||||||
|
|
||||||
|
class OfCatalyst(CMakePackage):
|
||||||
|
"""Of-catalyst is a library for OpenFOAM that provides a runtime-selectable
|
||||||
|
function object for embedding ParaView Catalyst in-situ visualization
|
||||||
|
into arbitrary OpenFOAM simulations.
|
||||||
|
Supports in-situ conversion of the following types:
|
||||||
|
1) finite volume meshes and fields, single or multi-region;
|
||||||
|
2) finite area meshes and fields, single region;
|
||||||
|
3) lagrangian (clouds), single or multiple clouds.
|
||||||
|
This offering is part of the community repository supported by OpenCFD Ltd,
|
||||||
|
producer and distributor of the OpenFOAM software via www.openfoam.com,
|
||||||
|
and owner of the OPENFOAM trademark.
|
||||||
|
OpenCFD Ltd has been developing and releasing OpenFOAM since its debut
|
||||||
|
in 2004.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Currently only via git
|
||||||
|
homepage = "https://develop.openfoam.com/Community/catalyst"
|
||||||
|
git = "https://develop.openfoam.com/Community/catalyst.git"
|
||||||
|
|
||||||
|
version('develop', branch='develop')
|
||||||
|
version('1806', tag='v1806')
|
||||||
|
|
||||||
|
variant('full', default=False, description='Build against paraview (full) or catalyst (light)')
|
||||||
|
|
||||||
|
depends_on('openfoam-com@1806', when='@1806', type=('build', 'link', 'run'))
|
||||||
|
depends_on('openfoam-com@develop', when='@develop', type=('build', 'link', 'run'))
|
||||||
|
depends_on('catalyst@5.5:', when='~full')
|
||||||
|
depends_on('paraview@5.5:+osmesa~qt', when='+full')
|
||||||
|
|
||||||
|
root_cmakelists_dir = 'src/catalyst'
|
||||||
|
|
||||||
|
def cmake_args(self):
|
||||||
|
"""Populate cmake arguments for ParaView."""
|
||||||
|
cmake_args = [
|
||||||
|
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY:PATH=%s' % join_path(
|
||||||
|
self.stage.source_path,
|
||||||
|
'spack-build')
|
||||||
|
]
|
||||||
|
|
||||||
|
return cmake_args
|
@@ -405,16 +405,16 @@ def setup_environment(self, spack_env, run_env):
|
|||||||
|
|
||||||
# Unneeded bits
|
# Unneeded bits
|
||||||
# -------------
|
# -------------
|
||||||
'FOAM_SETTINGS', # Do not use with modules
|
# 'FOAM_SETTINGS', # Do not use with modules
|
||||||
'FOAM_INST_DIR', # Old
|
# 'FOAM_INST_DIR', # Old
|
||||||
'FOAM_(APP|ETC|SRC|SOLVERS|UTILITIES)',
|
# 'FOAM_(APP|ETC|SRC|SOLVERS|UTILITIES)',
|
||||||
# 'FOAM_TUTORIALS', # can be useful
|
# 'FOAM_TUTORIALS', # can be useful
|
||||||
'WM_OSTYPE', # Purely optional value
|
# 'WM_OSTYPE', # Purely optional value
|
||||||
|
|
||||||
# Third-party cruft - only used for orig compilation
|
# Third-party cruft - only used for orig compilation
|
||||||
# -----------------
|
# -----------------
|
||||||
'[A-Z].*_ARCH_PATH',
|
'[A-Z].*_ARCH_PATH',
|
||||||
'(KAHIP|METIS|SCOTCH)_VERSION',
|
# '(KAHIP|METIS|SCOTCH)_VERSION',
|
||||||
|
|
||||||
# User-specific
|
# User-specific
|
||||||
# -------------
|
# -------------
|
||||||
@@ -426,6 +426,7 @@ def setup_environment(self, spack_env, run_env):
|
|||||||
])
|
])
|
||||||
|
|
||||||
run_env.extend(mods)
|
run_env.extend(mods)
|
||||||
|
spack_env.extend(mods)
|
||||||
minimal = False
|
minimal = False
|
||||||
tty.info('OpenFOAM bashrc env: {0}'.format(bashrc))
|
tty.info('OpenFOAM bashrc env: {0}'.format(bashrc))
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -436,8 +437,11 @@ def setup_environment(self, spack_env, run_env):
|
|||||||
tty.info('OpenFOAM minimal env {0}'.format(self.prefix))
|
tty.info('OpenFOAM minimal env {0}'.format(self.prefix))
|
||||||
run_env.set('FOAM_PROJECT_DIR', self.projectdir)
|
run_env.set('FOAM_PROJECT_DIR', self.projectdir)
|
||||||
run_env.set('WM_PROJECT_DIR', self.projectdir)
|
run_env.set('WM_PROJECT_DIR', self.projectdir)
|
||||||
|
spack_env.set('FOAM_PROJECT_DIR', self.projectdir)
|
||||||
|
spack_env.set('WM_PROJECT_DIR', self.projectdir)
|
||||||
for d in ['wmake', self.archbin]: # bin added automatically
|
for d in ['wmake', self.archbin]: # bin added automatically
|
||||||
run_env.prepend_path('PATH', join_path(self.projectdir, d))
|
run_env.prepend_path('PATH', join_path(self.projectdir, d))
|
||||||
|
spack_env.prepend_path('PATH', join_path(self.projectdir, d))
|
||||||
|
|
||||||
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
|
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
|
||||||
"""Location of the OpenFOAM project directory.
|
"""Location of the OpenFOAM project directory.
|
||||||
@@ -445,7 +449,7 @@ def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
|
|||||||
variable since it would mask the normal OpenFOAM cleanup of
|
variable since it would mask the normal OpenFOAM cleanup of
|
||||||
previous versions.
|
previous versions.
|
||||||
"""
|
"""
|
||||||
spack_env.set('FOAM_PROJECT_DIR', self.projectdir)
|
self.setup_environment(spack_env, run_env)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def projectdir(self):
|
def projectdir(self):
|
||||||
|
@@ -59,7 +59,8 @@ class Paraview(CMakePackage):
|
|||||||
depends_on('libpng')
|
depends_on('libpng')
|
||||||
depends_on('libtiff')
|
depends_on('libtiff')
|
||||||
depends_on('libxml2')
|
depends_on('libxml2')
|
||||||
# depends_on('netcdf')
|
depends_on('netcdf')
|
||||||
|
depends_on('expat')
|
||||||
# depends_on('netcdf-cxx')
|
# depends_on('netcdf-cxx')
|
||||||
# depends_on('protobuf') # version mismatches?
|
# depends_on('protobuf') # version mismatches?
|
||||||
# depends_on('sqlite') # external version not supported
|
# depends_on('sqlite') # external version not supported
|
||||||
@@ -74,6 +75,9 @@ class Paraview(CMakePackage):
|
|||||||
# Broken installation (ui_pqExportStateWizard.h) - fixed in 5.2.0
|
# Broken installation (ui_pqExportStateWizard.h) - fixed in 5.2.0
|
||||||
patch('ui_pqExportStateWizard.patch', when='@:5.1.2')
|
patch('ui_pqExportStateWizard.patch', when='@:5.1.2')
|
||||||
|
|
||||||
|
# Broken vtk-m config. Upstream catalyst changes
|
||||||
|
patch('vtkm-catalyst-pv551.patch', when='@5.5.0:5.5.2')
|
||||||
|
|
||||||
def url_for_version(self, version):
|
def url_for_version(self, version):
|
||||||
"""Handle ParaView version-based custom URLs."""
|
"""Handle ParaView version-based custom URLs."""
|
||||||
if version < Version('5.1.0'):
|
if version < Version('5.1.0'):
|
||||||
@@ -81,34 +85,50 @@ def url_for_version(self, version):
|
|||||||
else:
|
else:
|
||||||
return self._urlfmt.format(version.up_to(2), version, '')
|
return self._urlfmt.format(version.up_to(2), version, '')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def paraview_subdir(self):
|
||||||
|
"""The paraview subdirectory name as paraview-major.minor"""
|
||||||
|
return 'paraview-{0}'.format(self.spec.version.up_to(2))
|
||||||
|
|
||||||
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
|
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
|
||||||
if os.path.isdir(self.prefix.lib64):
|
if os.path.isdir(self.prefix.lib64):
|
||||||
lib_dir = self.prefix.lib64
|
lib_dir = self.prefix.lib64
|
||||||
else:
|
else:
|
||||||
lib_dir = self.prefix.lib
|
lib_dir = self.prefix.lib
|
||||||
paraview_version = 'paraview-%s' % self.spec.version.up_to(2)
|
spack_env.set('ParaView_DIR', self.prefix)
|
||||||
spack_env.set('PARAVIEW_VTK_DIR',
|
spack_env.set('PARAVIEW_VTK_DIR',
|
||||||
join_path(lib_dir, 'cmake', paraview_version))
|
join_path(lib_dir, 'cmake', self.paraview_subdir))
|
||||||
|
|
||||||
def setup_environment(self, spack_env, run_env):
|
def setup_environment(self, spack_env, run_env):
|
||||||
|
# paraview 5.5 and later
|
||||||
|
# - cmake under lib/cmake/paraview-5.5
|
||||||
|
# - libs under lib
|
||||||
|
# - python bits under lib/python2.8/site-packages
|
||||||
if os.path.isdir(self.prefix.lib64):
|
if os.path.isdir(self.prefix.lib64):
|
||||||
lib_dir = self.prefix.lib64
|
lib_dir = self.prefix.lib64
|
||||||
else:
|
else:
|
||||||
lib_dir = self.prefix.lib
|
lib_dir = self.prefix.lib
|
||||||
paraview_version = 'paraview-%s' % self.spec.version.up_to(2)
|
|
||||||
run_env.prepend_path('LIBRARY_PATH', join_path(lib_dir,
|
run_env.set('ParaView_DIR', self.prefix)
|
||||||
paraview_version))
|
|
||||||
run_env.prepend_path('LD_LIBRARY_PATH', join_path(lib_dir,
|
|
||||||
paraview_version))
|
|
||||||
run_env.set('PARAVIEW_VTK_DIR',
|
run_env.set('PARAVIEW_VTK_DIR',
|
||||||
join_path(lib_dir, 'cmake', paraview_version))
|
join_path(lib_dir, 'cmake', self.paraview_subdir))
|
||||||
|
|
||||||
|
if self.spec.version <= Version('5.4.1'):
|
||||||
|
lib_dir = join_path(lib_dir, self.paraview_subdir)
|
||||||
|
|
||||||
|
run_env.prepend_path('LIBRARY_PATH', lib_dir)
|
||||||
|
run_env.prepend_path('LD_LIBRARY_PATH', lib_dir)
|
||||||
|
|
||||||
if '+python' in self.spec:
|
if '+python' in self.spec:
|
||||||
run_env.prepend_path('PYTHONPATH', join_path(lib_dir,
|
if self.spec.version <= Version('5.4.1'):
|
||||||
paraview_version))
|
pv_pydir = join_path(lib_dir, 'site-packages')
|
||||||
run_env.prepend_path('PYTHONPATH', join_path(lib_dir,
|
run_env.prepend_path('PYTHONPATH', pv_pydir)
|
||||||
paraview_version, 'site-packages'))
|
run_env.prepend_path('PYTHONPATH', join_path(pv_pydir, 'vtk'))
|
||||||
run_env.prepend_path('PYTHONPATH', join_path(lib_dir,
|
else:
|
||||||
paraview_version, 'site-packages', 'vtk'))
|
python_version = self.spec['python'].version.up_to(2)
|
||||||
|
run_env.prepend_path('PYTHONPATH', join_path(lib_dir,
|
||||||
|
'python{0}'.format(python_version),
|
||||||
|
'site-packages'))
|
||||||
|
|
||||||
def cmake_args(self):
|
def cmake_args(self):
|
||||||
"""Populate cmake arguments for ParaView."""
|
"""Populate cmake arguments for ParaView."""
|
||||||
@@ -139,7 +159,8 @@ def nvariant_bool(feature):
|
|||||||
'-DVTK_USE_SYSTEM_HDF5:BOOL=%s' % variant_bool('+hdf5'),
|
'-DVTK_USE_SYSTEM_HDF5:BOOL=%s' % variant_bool('+hdf5'),
|
||||||
'-DVTK_USE_SYSTEM_JPEG:BOOL=ON',
|
'-DVTK_USE_SYSTEM_JPEG:BOOL=ON',
|
||||||
'-DVTK_USE_SYSTEM_LIBXML2:BOOL=ON',
|
'-DVTK_USE_SYSTEM_LIBXML2:BOOL=ON',
|
||||||
'-DVTK_USE_SYSTEM_NETCDF:BOOL=OFF',
|
'-DVTK_USE_SYSTEM_NETCDF:BOOL=ON',
|
||||||
|
'-DVTK_USE_SYSTEM_EXPAT:BOOL=ON',
|
||||||
'-DVTK_USE_SYSTEM_TIFF:BOOL=ON',
|
'-DVTK_USE_SYSTEM_TIFF:BOOL=ON',
|
||||||
'-DVTK_USE_SYSTEM_ZLIB:BOOL=ON',
|
'-DVTK_USE_SYSTEM_ZLIB:BOOL=ON',
|
||||||
]
|
]
|
||||||
|
@@ -0,0 +1,510 @@
|
|||||||
|
# The VTK-m changes are slated for paraview-5.5.x
|
||||||
|
#
|
||||||
|
# The catalyst changes (the working directory for output) are slated for
|
||||||
|
# paraview-5.6.
|
||||||
|
# They are API-compatible with paraview-5.5 but not ABI compatible.
|
||||||
|
#
|
||||||
|
# https://gitlab.kitware.com/vtk/vtk-m/merge_requests/1166
|
||||||
|
# https://gitlab.kitware.com/paraview/paraview/merge_requests/2433
|
||||||
|
# https://gitlab.kitware.com/paraview/paraview/merge_requests/2436
|
||||||
|
#
|
||||||
|
--- ParaView-v5.5.0/VTK/ThirdParty/vtkm/vtk-m/CMake/VTKmDetermineVersion.cmake.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ ParaView-v5.5.0/VTK/ThirdParty/vtkm/vtk-m/CMake/VTKmDetermineVersion.cmake 2018-04-23 12:00:23.708544206 +0200
|
||||||
|
@@ -51,6 +51,8 @@
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_STRIP_TRAILING_WHITESPACE)
|
||||||
|
+ else()
|
||||||
|
+ set(output)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(result 0)
|
||||||
|
@@ -75,7 +77,7 @@
|
||||||
|
|
||||||
|
# Extracts components from a version string. See determine_version() for usage.
|
||||||
|
function(extract_version_components version_string var_prefix)
|
||||||
|
- string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)[-]*(.*)"
|
||||||
|
+ string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)[-]*(.*)$"
|
||||||
|
version_matches "${version_string}")
|
||||||
|
if(CMAKE_MATCH_0)
|
||||||
|
set(full ${CMAKE_MATCH_0})
|
||||||
|
--- ParaView-v5.5.0/CoProcessing/Catalyst/vtkCPProcessor.cxx.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ ParaView-v5.5.0/CoProcessing/Catalyst/vtkCPProcessor.cxx 2018-05-11 12:02:26.894772713 +0200
|
||||||
|
@@ -38,6 +38,7 @@
|
||||||
|
#include "vtkStringArray.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
+#include <vtksys/SystemTools.hxx>
|
||||||
|
|
||||||
|
struct vtkCPProcessorInternals
|
||||||
|
{
|
||||||
|
@@ -47,12 +48,13 @@
|
||||||
|
};
|
||||||
|
|
||||||
|
vtkStandardNewMacro(vtkCPProcessor);
|
||||||
|
-vtkMultiProcessController* vtkCPProcessor::Controller = NULL;
|
||||||
|
+vtkMultiProcessController* vtkCPProcessor::Controller = nullptr;
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
vtkCPProcessor::vtkCPProcessor()
|
||||||
|
{
|
||||||
|
this->Internal = new vtkCPProcessorInternals;
|
||||||
|
- this->InitializationHelper = NULL;
|
||||||
|
+ this->InitializationHelper = nullptr;
|
||||||
|
+ this->WorkingDirectory = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
@@ -61,14 +63,15 @@
|
||||||
|
if (this->Internal)
|
||||||
|
{
|
||||||
|
delete this->Internal;
|
||||||
|
- this->Internal = NULL;
|
||||||
|
+ this->Internal = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->InitializationHelper)
|
||||||
|
{
|
||||||
|
this->InitializationHelper->Delete();
|
||||||
|
- this->InitializationHelper = NULL;
|
||||||
|
+ this->InitializationHelper = nullptr;
|
||||||
|
}
|
||||||
|
+ this->SetWorkingDirectory(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
@@ -95,7 +98,7 @@
|
||||||
|
{
|
||||||
|
if (which < 0 || which >= this->GetNumberOfPipelines())
|
||||||
|
{
|
||||||
|
- return NULL;
|
||||||
|
+ return nullptr;
|
||||||
|
}
|
||||||
|
int counter = 0;
|
||||||
|
vtkCPProcessorInternals::PipelineListIterator iter = this->Internal->Pipelines.begin();
|
||||||
|
@@ -108,7 +111,7 @@
|
||||||
|
counter++;
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
- return NULL;
|
||||||
|
+ return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
@@ -130,17 +133,41 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
-int vtkCPProcessor::Initialize()
|
||||||
|
+int vtkCPProcessor::Initialize(const char* workingDirectory)
|
||||||
|
{
|
||||||
|
- if (this->InitializationHelper == NULL)
|
||||||
|
+ if (this->InitializationHelper == nullptr)
|
||||||
|
{
|
||||||
|
this->InitializationHelper = this->NewInitializationHelper();
|
||||||
|
}
|
||||||
|
+ // make sure the directory exists here so that we only do it once
|
||||||
|
+ if (workingDirectory)
|
||||||
|
+ {
|
||||||
|
+ vtkMultiProcessController* controller = vtkMultiProcessController::GetGlobalController();
|
||||||
|
+ int success = 1;
|
||||||
|
+ if (controller == nullptr || controller->GetLocalProcessId() == 0)
|
||||||
|
+ {
|
||||||
|
+ success = vtksys::SystemTools::MakeDirectory(workingDirectory) == true ? 1 : 0;
|
||||||
|
+ if (success == 0)
|
||||||
|
+ {
|
||||||
|
+ vtkWarningMacro("Could not make "
|
||||||
|
+ << workingDirectory << " directory. "
|
||||||
|
+ << "Results will be generated in current working directory instead.");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (controller)
|
||||||
|
+ {
|
||||||
|
+ controller->Broadcast(&success, 1, 0);
|
||||||
|
+ }
|
||||||
|
+ if (success)
|
||||||
|
+ {
|
||||||
|
+ this->SetWorkingDirectory(workingDirectory);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
-int vtkCPProcessor::Initialize(vtkMPICommunicatorOpaqueComm& comm)
|
||||||
|
+int vtkCPProcessor::Initialize(vtkMPICommunicatorOpaqueComm& comm, const char* workingDirectory)
|
||||||
|
{
|
||||||
|
#ifdef PARAVIEW_USE_MPI
|
||||||
|
if (vtkCPProcessor::Controller)
|
||||||
|
@@ -148,7 +175,7 @@
|
||||||
|
vtkErrorMacro("Can only initialize with a communicator once per process.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
- if (this->InitializationHelper == NULL)
|
||||||
|
+ if (this->InitializationHelper == nullptr)
|
||||||
|
{
|
||||||
|
vtkMPICommunicator* communicator = vtkMPICommunicator::New();
|
||||||
|
communicator->InitializeExternal(&comm);
|
||||||
|
@@ -157,12 +184,12 @@
|
||||||
|
this->Controller = controller;
|
||||||
|
this->Controller->SetGlobalController(controller);
|
||||||
|
communicator->Delete();
|
||||||
|
- return this->Initialize();
|
||||||
|
+ return this->Initialize(workingDirectory);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
static_cast<void>(&comm); // get rid of variable not used warning
|
||||||
|
- return this->Initialize();
|
||||||
|
+ return this->Initialize(workingDirectory);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -225,6 +252,13 @@
|
||||||
|
input->GetFieldData()->AddArray(catalystChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ std::string originalWorkingDirectory;
|
||||||
|
+ if (this->WorkingDirectory)
|
||||||
|
+ {
|
||||||
|
+ originalWorkingDirectory = vtksys::SystemTools::GetCurrentWorkingDirectory();
|
||||||
|
+ vtksys::SystemTools::ChangeDirectory(this->WorkingDirectory);
|
||||||
|
+ }
|
||||||
|
for (vtkCPProcessorInternals::PipelineListIterator iter = this->Internal->Pipelines.begin();
|
||||||
|
iter != this->Internal->Pipelines.end(); iter++)
|
||||||
|
{
|
||||||
|
@@ -248,6 +282,10 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (originalWorkingDirectory.empty() == false)
|
||||||
|
+ {
|
||||||
|
+ vtksys::SystemTools::ChangeDirectory(originalWorkingDirectory);
|
||||||
|
+ }
|
||||||
|
// we want to reset everything here to make sure that new information
|
||||||
|
// is properly passed in the next time.
|
||||||
|
dataDescription->ResetAll();
|
||||||
|
@@ -259,7 +297,7 @@
|
||||||
|
{
|
||||||
|
if (this->Controller)
|
||||||
|
{
|
||||||
|
- this->Controller->SetGlobalController(NULL);
|
||||||
|
+ this->Controller->SetGlobalController(nullptr);
|
||||||
|
this->Controller->Finalize(1);
|
||||||
|
this->Controller->Delete();
|
||||||
|
}
|
||||||
|
--- ParaView-v5.5.0/CoProcessing/Catalyst/vtkCPProcessor.h.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ ParaView-v5.5.0/CoProcessing/Catalyst/vtkCPProcessor.h 2018-05-11 12:02:26.894772713 +0200
|
||||||
|
@@ -76,14 +76,16 @@
|
||||||
|
virtual void RemoveAllPipelines();
|
||||||
|
|
||||||
|
/// Initialize the co-processor. Returns 1 if successful and 0
|
||||||
|
- /// otherwise.
|
||||||
|
/// otherwise. If Catalyst is built with MPI then Initialize()
|
||||||
|
/// can also be called with a specific MPI communicator if
|
||||||
|
/// MPI_COMM_WORLD isn't the proper one. Catalyst is initialized
|
||||||
|
- /// to use MPI_COMM_WORLD by default.
|
||||||
|
- virtual int Initialize();
|
||||||
|
+ /// to use MPI_COMM_WORLD by default. Both methods have an optional
|
||||||
|
+ /// workingDirectory argument which will set *WorkingDirectory* so
|
||||||
|
+ /// that files will be put relative to this directory.
|
||||||
|
+ virtual int Initialize(const char* workingDirectory = nullptr);
|
||||||
|
#ifndef __WRAP__
|
||||||
|
- virtual int Initialize(vtkMPICommunicatorOpaqueComm& comm);
|
||||||
|
+ virtual int Initialize(
|
||||||
|
+ vtkMPICommunicatorOpaqueComm& comm, const char* workingDirectory = nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// The Catalyst input field data string array name. This array will
|
||||||
|
@@ -111,6 +113,13 @@
|
||||||
|
/// implementation an opportunity to clean up, before it is destroyed.
|
||||||
|
virtual int Finalize();
|
||||||
|
|
||||||
|
+ /// Get the current working directory for outputting Catalyst files.
|
||||||
|
+ /// If not set then Catalyst output files will be relative to the
|
||||||
|
+ /// current working directory. This will not affect where Catalyst
|
||||||
|
+ /// looks for Python scripts. *WorkingDirectory* gets set through
|
||||||
|
+ /// the *Initialize()* methods.
|
||||||
|
+ vtkGetStringMacro(WorkingDirectory);
|
||||||
|
+
|
||||||
|
protected:
|
||||||
|
vtkCPProcessor();
|
||||||
|
virtual ~vtkCPProcessor();
|
||||||
|
@@ -118,6 +127,11 @@
|
||||||
|
/// Create a new instance of the InitializationHelper.
|
||||||
|
virtual vtkObject* NewInitializationHelper();
|
||||||
|
|
||||||
|
+ /// Set the current working directory for outputting Catalyst files.
|
||||||
|
+ /// This is a protected method since simulation code adaptors should
|
||||||
|
+ /// set this through the *Initialize()* methods.
|
||||||
|
+ vtkSetStringMacro(WorkingDirectory);
|
||||||
|
+
|
||||||
|
private:
|
||||||
|
vtkCPProcessor(const vtkCPProcessor&) = delete;
|
||||||
|
void operator=(const vtkCPProcessor&) = delete;
|
||||||
|
@@ -125,6 +139,7 @@
|
||||||
|
vtkCPProcessorInternals* Internal;
|
||||||
|
vtkObject* InitializationHelper;
|
||||||
|
static vtkMultiProcessController* Controller;
|
||||||
|
+ char* WorkingDirectory;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
--- ParaView-v5.5.0/CoProcessing/Catalyst/vtkCPXMLPWriterPipeline.cxx.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ ParaView-v5.5.0/CoProcessing/Catalyst/vtkCPXMLPWriterPipeline.cxx 2018-05-11 12:02:26.894772713 +0200
|
||||||
|
@@ -31,6 +31,7 @@
|
||||||
|
#include <vtkSmartPointer.h>
|
||||||
|
#include <vtkUnstructuredGrid.h>
|
||||||
|
|
||||||
|
+#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
@@ -174,7 +175,7 @@
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < dataDescription->GetNumberOfInputDescriptions(); i++)
|
||||||
|
{
|
||||||
|
- const char* inputName = dataDescription->GetInputDescriptionName(i);
|
||||||
|
+ std::string inputName = dataDescription->GetInputDescriptionName(i);
|
||||||
|
vtkCPInputDataDescription* idd = dataDescription->GetInputDescription(i);
|
||||||
|
vtkDataObject* grid = idd->GetGrid();
|
||||||
|
if (grid == nullptr)
|
||||||
|
@@ -206,6 +207,8 @@
|
||||||
|
vtkSMStringVectorProperty* fileName =
|
||||||
|
vtkSMStringVectorProperty::SafeDownCast(writer->GetProperty("FileName"));
|
||||||
|
|
||||||
|
+ // If we have a / in the channel name we take it out of the filename we're going to write to
|
||||||
|
+ inputName.erase(std::remove(inputName.begin(), inputName.end(), '/'), inputName.end());
|
||||||
|
std::ostringstream o;
|
||||||
|
if (this->Path.empty() == false)
|
||||||
|
{
|
||||||
|
--- ParaView-v5.5.0/Wrapping/Python/paraview/coprocessing.py.orig 2018-04-06 22:03:33.000000000 +0200
|
||||||
|
+++ ParaView-v5.5.0/Wrapping/Python/paraview/coprocessing.py 2018-05-11 12:02:27.038772408 +0200
|
||||||
|
@@ -11,22 +11,12 @@
|
||||||
|
from paraview.vtk.vtkPVVTKExtensionsCore import *
|
||||||
|
import math
|
||||||
|
|
||||||
|
-# -----------------------------------------------------------------------------
|
||||||
|
-def IsInModulo(timestep, frequencyArray):
|
||||||
|
- """
|
||||||
|
- Return True if the given timestep is in one of the provided frequency.
|
||||||
|
- This can be interpreted as follow::
|
||||||
|
-
|
||||||
|
- isFM = IsInModulo(timestep, [2,3,7])
|
||||||
|
-
|
||||||
|
- is similar to::
|
||||||
|
+# If the user created a filename in a location that doesn't exist by default we'll
|
||||||
|
+# make the directory for them. This can be changed though by setting createDirectoriesIfNeeded
|
||||||
|
+# to False.
|
||||||
|
+createDirectoriesIfNeeded = True
|
||||||
|
|
||||||
|
- isFM = (timestep % 2 == 0) or (timestep % 3 == 0) or (timestep % 7 == 0)
|
||||||
|
- """
|
||||||
|
- for frequency in frequencyArray:
|
||||||
|
- if frequency > 0 and (timestep % frequency == 0):
|
||||||
|
- return True
|
||||||
|
- return False
|
||||||
|
+# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class CoProcessor(object):
|
||||||
|
"""Base class for co-processing Pipelines.
|
||||||
|
@@ -68,6 +58,9 @@
|
||||||
|
self.__CinemaTracks = {}
|
||||||
|
self.__InitialFrequencies = {}
|
||||||
|
self.__PrintEnsightFormatString = False
|
||||||
|
+ self.__TimeStepToStartOutputAt=0
|
||||||
|
+ self.__ForceOutputAtFirstCall=False
|
||||||
|
+ self.__FirstTimeStepIndex = None
|
||||||
|
|
||||||
|
def SetPrintEnsightFormatString(self, enable):
|
||||||
|
"""If outputting ExodusII files with the purpose of reading them into
|
||||||
|
@@ -87,6 +80,17 @@
|
||||||
|
"Incorrect argument type: %s, must be a dict" % type(frequencies))
|
||||||
|
self.__InitialFrequencies = frequencies
|
||||||
|
|
||||||
|
+ def SetInitialOutputOptions(self, timeStepToStartOutputAt, forceOutputAtFirstCall):
|
||||||
|
+ """Set the frequencies at which the pipeline needs to be updated.
|
||||||
|
+ Typically, this is called by the subclass once it has determined what
|
||||||
|
+ timesteps co-processing will be needed to be done.
|
||||||
|
+ frequencies is a map, with key->string name of for the simulation
|
||||||
|
+ input, and value is a list of frequencies.
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ self.__TimeStepToStartOutputAt=timeStepToStartOutputAt
|
||||||
|
+ self.__ForceOutputAtFirstCall=forceOutputAtFirstCall
|
||||||
|
+
|
||||||
|
def EnableLiveVisualization(self, enable, frequency = 1):
|
||||||
|
"""Call this method to enable live-visualization. When enabled,
|
||||||
|
DoLiveVisualization() will communicate with ParaView server if possible
|
||||||
|
@@ -115,7 +119,7 @@
|
||||||
|
# if this is a time step to do live then all of the inputs
|
||||||
|
# must be made available. note that we want the pipeline built
|
||||||
|
# before we do the actual first live connection.
|
||||||
|
- if self.__EnableLiveVisualization and timestep % self.__LiveVisualizationFrequency == 0 \
|
||||||
|
+ if self.__EnableLiveVisualization and self.NeedToOutput(timestep, self.__LiveVisualizationFrequency) \
|
||||||
|
and self.__LiveVisualizationLink:
|
||||||
|
if self.__LiveVisualizationLink.Initialize(servermanager.ActiveConnection.Session.GetSessionProxyManager()):
|
||||||
|
num_inputs = datadescription.GetNumberOfInputDescriptions()
|
||||||
|
@@ -132,13 +136,13 @@
|
||||||
|
# hasn't been set up yet). If we don't have live enabled
|
||||||
|
# we know that the output frequencies aren't changed and can
|
||||||
|
# just use the initial frequencies.
|
||||||
|
- if self.__InitialFrequencies or not self.__EnableLiveVisualization:
|
||||||
|
+ if self.__ForceOutputAtFirstCall or self.__InitialFrequencies or not self.__EnableLiveVisualization:
|
||||||
|
num_inputs = datadescription.GetNumberOfInputDescriptions()
|
||||||
|
for cc in range(num_inputs):
|
||||||
|
input_name = datadescription.GetInputDescriptionName(cc)
|
||||||
|
|
||||||
|
freqs = self.__InitialFrequencies.get(input_name, [])
|
||||||
|
- if self.__EnableLiveVisualization or ( self and IsInModulo(timestep, freqs) ):
|
||||||
|
+ if self.__EnableLiveVisualization or ( self and self.IsInModulo(timestep, freqs) ):
|
||||||
|
datadescription.GetInputDescription(cc).AllFieldsOn()
|
||||||
|
datadescription.GetInputDescription(cc).GenerateMeshOn()
|
||||||
|
else:
|
||||||
|
@@ -149,15 +153,14 @@
|
||||||
|
for writer in self.__WritersList:
|
||||||
|
frequency = writer.parameters.GetProperty(
|
||||||
|
"WriteFrequency").GetElement(0)
|
||||||
|
- if (timestep % frequency) == 0 or \
|
||||||
|
- datadescription.GetForceOutput() == True:
|
||||||
|
+ if self.NeedToOutput(timestep, frequency) or datadescription.GetForceOutput() == True:
|
||||||
|
writerinputs = cpstate.locate_simulation_inputs(writer)
|
||||||
|
for writerinput in writerinputs:
|
||||||
|
datadescription.GetInputDescriptionByName(writerinput).AllFieldsOn()
|
||||||
|
datadescription.GetInputDescriptionByName(writerinput).GenerateMeshOn()
|
||||||
|
|
||||||
|
for view in self.__ViewsList:
|
||||||
|
- if (view.cpFrequency and timestep % view.cpFrequency == 0) or \
|
||||||
|
+ if (view.cpFrequency and self.NeedToOutput(timestep, view.cpFrequency)) or \
|
||||||
|
datadescription.GetForceOutput() == True:
|
||||||
|
viewinputs = cpstate.locate_simulation_inputs_for_view(view)
|
||||||
|
for viewinput in viewinputs:
|
||||||
|
@@ -192,8 +195,7 @@
|
||||||
|
for writer in self.__WritersList:
|
||||||
|
frequency = writer.parameters.GetProperty(
|
||||||
|
"WriteFrequency").GetElement(0)
|
||||||
|
- if (timestep % frequency) == 0 or \
|
||||||
|
- datadescription.GetForceOutput() == True:
|
||||||
|
+ if self.NeedToOutput(timestep, frequency) or datadescription.GetForceOutput() == True:
|
||||||
|
fileName = writer.parameters.GetProperty("FileName").GetElement(0)
|
||||||
|
paddingamount = writer.parameters.GetProperty("PaddingAmount").GetElement(0)
|
||||||
|
helperName = writer.GetXMLName()
|
||||||
|
@@ -203,6 +205,23 @@
|
||||||
|
else:
|
||||||
|
ts = str(timestep).rjust(paddingamount, '0')
|
||||||
|
writer.FileName = fileName.replace("%t", ts)
|
||||||
|
+ if '/' in writer.FileName and createDirectoriesIfNeeded:
|
||||||
|
+ oktowrite = [1.]
|
||||||
|
+ import vtk
|
||||||
|
+ comm = vtk.vtkMultiProcessController.GetGlobalController()
|
||||||
|
+ if comm.GetLocalProcessId() == 0:
|
||||||
|
+ import os
|
||||||
|
+ newDir = writer.FileName[0:writer.FileName.rfind('/')]
|
||||||
|
+ try:
|
||||||
|
+ os.makedirs(newDir)
|
||||||
|
+ except OSError:
|
||||||
|
+ if not os.path.isdir(newDir):
|
||||||
|
+ print ("ERROR: Cannot make directory for", writer.FileName, ". No data will be written.")
|
||||||
|
+ oktowrite[0] = 0.
|
||||||
|
+ comm.Broadcast(oktowrite, 1, 0)
|
||||||
|
+ if oktowrite[0] == 0:
|
||||||
|
+ # we can't make the directory so no reason to update the pipeline
|
||||||
|
+ return
|
||||||
|
writer.UpdatePipeline(datadescription.GetTime())
|
||||||
|
|
||||||
|
def WriteImages(self, datadescription, rescale_lookuptable=False,
|
||||||
|
@@ -240,7 +259,7 @@
|
||||||
|
|
||||||
|
cinema_dirs = []
|
||||||
|
for view in self.__ViewsList:
|
||||||
|
- if (view.cpFrequency and timestep % view.cpFrequency == 0) or \
|
||||||
|
+ if (view.cpFrequency and self.NeedToOutput(timestep, view.cpFrequency)) or \
|
||||||
|
datadescription.GetForceOutput() == True:
|
||||||
|
fname = view.cpFileName
|
||||||
|
ts = str(timestep).rjust(padding_amount, '0')
|
||||||
|
@@ -267,6 +286,24 @@
|
||||||
|
if dirname:
|
||||||
|
cinema_dirs.append(dirname)
|
||||||
|
else:
|
||||||
|
+ if '/' in fname and createDirectoriesIfNeeded:
|
||||||
|
+ oktowrite = [1.]
|
||||||
|
+ import vtk
|
||||||
|
+ comm = vtk.vtkMultiProcessController.GetGlobalController()
|
||||||
|
+ if comm.GetLocalProcessId() == 0:
|
||||||
|
+ import os
|
||||||
|
+ newDir = fname[0:fname.rfind('/')]
|
||||||
|
+ try:
|
||||||
|
+ os.makedirs(newDir)
|
||||||
|
+ except OSError:
|
||||||
|
+ if not os.path.isdir(newDir):
|
||||||
|
+ print ("ERROR: Cannot make directory for", fname, ". No image will be output.")
|
||||||
|
+ oktowrite[0] = 0.
|
||||||
|
+ comm.Broadcast(oktowrite, 1, 0)
|
||||||
|
+ if oktowrite[0] == 0:
|
||||||
|
+ # we can't make the directory so no reason to update the pipeline
|
||||||
|
+ return
|
||||||
|
+
|
||||||
|
if image_quality is None and fname.endswith('png'):
|
||||||
|
# for png quality = 0 means no compression. compression can be a potentially
|
||||||
|
# very costly serial operation on process 0
|
||||||
|
@@ -307,7 +344,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
timeStep = datadescription.GetTimeStep()
|
||||||
|
- if self.__EnableLiveVisualization and timeStep % self.__LiveVisualizationFrequency == 0:
|
||||||
|
+ if self.__EnableLiveVisualization and self.NeedToOutput(timeStep, self.__LiveVisualizationFrequency):
|
||||||
|
if not self.__LiveVisualizationLink.Initialize(servermanager.ActiveConnection.Session.GetSessionProxyManager()):
|
||||||
|
return
|
||||||
|
|
||||||
|
@@ -412,7 +449,7 @@
|
||||||
|
"""
|
||||||
|
controller = servermanager.ParaViewPipelineController()
|
||||||
|
# assume that a client only proxy with the same name as a writer
|
||||||
|
- # is available in "insitu_writer_paramters"
|
||||||
|
+ # is available in "insitu_writer_parameters"
|
||||||
|
|
||||||
|
# Since coprocessor sometimes pass writer as a custom object and not
|
||||||
|
# a proxy, we need to handle that. Just creating any arbitrary writer
|
||||||
|
@@ -666,3 +703,42 @@
|
||||||
|
#restore what we showed
|
||||||
|
pv_introspect.restore_visibility(pxystate)
|
||||||
|
return os.path.basename(vfname)
|
||||||
|
+
|
||||||
|
+ def IsInModulo(self, timestep, frequencies):
|
||||||
|
+ """
|
||||||
|
+ Return True if the given timestep is in one of the provided frequency.
|
||||||
|
+ This can be interpreted as follow::
|
||||||
|
+
|
||||||
|
+ isFM = IsInModulo(timestep-timeStepToStartOutputAt, [2,3,7])
|
||||||
|
+
|
||||||
|
+ is similar to::
|
||||||
|
+
|
||||||
|
+ isFM = (timestep-timeStepToStartOutputAt % 2 == 0) or (timestep-timeStepToStartOutputAt % 3 == 0) or (timestep-timeStepToStartOutputAt % 7 == 0)
|
||||||
|
+
|
||||||
|
+ The timeStepToStartOutputAt is the first timestep that will potentially be output.
|
||||||
|
+ """
|
||||||
|
+ if timestep < self.__TimeStepToStartOutputAt and not self.__ForceOutputAtFirstCall:
|
||||||
|
+ return False
|
||||||
|
+ for frequency in frequencies:
|
||||||
|
+ if frequency > 0 and self.NeedToOutput(timestep, frequency):
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ def NeedToOutput(self, timestep, frequency):
|
||||||
|
+ """
|
||||||
|
+ Return True if we need to output based on the input timestep and frequency. Checks based
|
||||||
|
+ __FirstTimeStepIndex, __FirstTimeStepIndex, __ForceOutputAtFirstCall and __TimeStepToStartOutputAt
|
||||||
|
+ member variables.
|
||||||
|
+ """
|
||||||
|
+ if self.__FirstTimeStepIndex == None:
|
||||||
|
+ self.__FirstTimeStepIndex = timestep
|
||||||
|
+
|
||||||
|
+ if self.__ForceOutputAtFirstCall and self.__FirstTimeStepIndex == timestep:
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ if self.__TimeStepToStartOutputAt <= timestep and (timestep-self.__TimeStepToStartOutputAt) % frequency == 0:
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
+ return False
|
Reference in New Issue
Block a user