diff --git a/CMakeLists.txt b/CMakeLists.txt index 2383cdc4ad72892a589501889f0615152d52ec22..ed252ac9de47b913582dff7294f4e57ca3cb443b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ if(BUILD_TESTING) comin_test_add_plugin(TEST catalyst_test NAME "catalyst_adapter" PLUGIN_LIBRARY "$<TARGET_FILE:catalyst_adapter>" - OPTIONS "/home/nils/projects/comin/catalyst_adaptor/LiveOnly.py" + OPTIONS "/home/nils/projects/comin/catalyst_adaptor/pvExample.py" + # OPTIONS "/home/nils/projects/comin/catalyst_adaptor/gridwriter.py" ) endif() diff --git a/catalyst_adapter.cpp b/catalyst_adapter.cpp index 856ce20f345030444a301e143ccf430cde5e51c9..ec410eba9b404eb384a96c14a7dabe6b8f928f94 100644 --- a/catalyst_adapter.cpp +++ b/catalyst_adapter.cpp @@ -1,15 +1,17 @@ #include <iostream> #include <vector> +#include<unistd.h> #include <comin.h> #include <catalyst.hpp> -#include "parse_isotime.hpp" - int ierr = COMIN_SUCCESS; +void catalyst_adapter_secondary_constructor(); void catalyst_adapter_execute(); void catalyst_adapter_destruct(); +static conduit_cpp::Node catalyst_exec_params; + extern "C"{ // avoid name-mangling void comin_main(){ conduit_cpp::Node catalyst_init_params; @@ -32,26 +34,15 @@ extern "C"{ // avoid name-mangling } about_node.print(); + comin_callback_register(EP_SECONDARY_CONSTRUCTOR, catalyst_adapter_secondary_constructor, &ierr); comin_callback_register(EP_ATM_WRITE_OUTPUT_BEFORE, catalyst_adapter_execute, &ierr); comin_callback_register(EP_DESTRUCTOR, catalyst_adapter_destruct, &ierr); } } -void catalyst_adapter_execute(){ - conduit_cpp::Node catalyst_exec_params; - - static int64_t cycle = 0; - catalyst_exec_params["catalyst/state/cycle"] = cycle; - cycle++; - - const char* datetime_ptr = NULL; - int datetime_len = 0; - comin_current_get_datetime(&datetime_ptr, &datetime_len, &ierr); - - auto t = parse_isotime(std::string(datetime_ptr, datetime_len)); - double time = std::chrono::duration_cast<std::chrono::seconds>(t.time_since_epoch()).count(); - catalyst_exec_params["catalyst/state/time"] = time; +void catalyst_adapter_secondary_constructor(){ + // prepare the execute node for(int jg = 1; jg<=comin_descrdata_get_global_n_dom(); ++jg){ std::cout << "dom: " << jg << std::endl; auto channel = catalyst_exec_params[std::string("catalyst/channels/domain")+std::to_string(jg)]; @@ -88,21 +79,40 @@ void catalyst_adapter_execute(){ } channel["data/topologies/mesh/elements/connectivity"].set(vidx); - // dummy field - channel["data/fields/foo/association"] = "element"; - channel["data/fields/foo/topology"] = "mesh"; - channel["data/fields/foo/volume_dependend"] = false; - channel["data/fields/foo/values"].set(std::vector<double>(ncells, 42.0)); + for(void* it = comin_var_get_descr_list_head(); + it != nullptr; + it = comin_var_get_descr_list_next(it)){ + t_comin_var_descriptor var_desc; + comin_var_get_descr_list_var_desc(it, &var_desc, &ierr); + int zaxis_id = -1; + comin_metadata_get_integer(var_desc, "zaxis_id", &zaxis_id, &ierr); + if(var_desc.id == jg && + zaxis_id == COMIN_ZAXIS_2D){ + channel["data/fields/" + std::string(var_desc.name) + "/association"] = "element"; + channel["data/fields/" + std::string(var_desc.name) + "/topology"] = "mesh"; + channel["data/fields/" + std::string(var_desc.name) + "/volume_dependend"] = false; + int ep = EP_ATM_WRITE_OUTPUT_BEFORE; + void* handle = comin_var_get(1, &ep, var_desc, COMIN_FLAG_READ); + channel["data/fields/" + std::string(var_desc.name) + "/values"] + .set_external(comin_var_get_ptr(handle), ncells); + } + } } +} - //std::cout << catalyst_exec_params.to_json() << std::endl; +void catalyst_adapter_execute(){ + static int64_t cycle = 0; + catalyst_exec_params["catalyst/state/cycle"] = cycle; + catalyst_exec_params["catalyst/state/time"] = cycle; + cycle++; enum catalyst_status err = catalyst_execute(conduit_cpp::c_node(&catalyst_exec_params)); if (err != catalyst_status_ok) { printf("Failed to execute Catalyst: %d\n", err); } + sleep(1); } diff --git a/gridwriter.py b/gridwriter.py new file mode 100644 index 0000000000000000000000000000000000000000..1a339fb758d1dfb4a644e5a27d5b37a35343041a --- /dev/null +++ b/gridwriter.py @@ -0,0 +1,74 @@ +# script-version: 2.0 +# Sample Catalyst Python script to generate data outputs. +# One can use this directly or create a modified version +# to customize write frequency, output directory etc. + +#--------------------------------------------------------- +# Input parameters +#--------------------------------------------------------- +# Specify the Catalyst channel name +catalystChannel = "domain1" + +# Specify the write frequency +frequency = 1 + +# Specify the output directory. Ideally, this should be an +# absolute path to avoid confusion. +outputDirectory = "vtk" + +# Specify extractor type to use, if any. +# e.g. for CSV, set extractorType to 'CSV' +extractorType = None + +#--------------------------------------------------------- +from paraview.simple import * + +# Specify the Catalyst channel name +def create_extractor(data): + if extractorType is not None: + return CreateExtractor(extractorType, data, registrationName=extractorType) + + grid = data.GetClientSideObject().GetOutputDataObject(0) + if grid.IsA('vtkImageData'): + return CreateExtractor('VTI', data, registrationName='VTI') + elif grid.IsA('vtkRectilinearGrid'): + return CreateExtractor('VTR', data, registrationName='VTR') + elif grid.IsA('vtkStructuredGrid'): + return CreateExtractor('VTS', data, registrationName='VTS') + elif grid.IsA('vtkPolyData'): + return CreateExtractor('VTP', data, registrationName='VTP') + elif grid.IsA('vtkUnstructuredGrid'): + return CreateExtractor('VTU', data, registrationName='VTU') + elif grid.IsA('vtkUniformGridAMR'): + return CreateExtractor('VTH', data, registrationName='VTH') + elif grid.IsA('vtkMultiBlockDataSet'): + return CreateExtractor('VTM', data, registrationName='VTM') + elif grid.IsA('vtkPartitionedDataSet'): + return CreateExtractor('VTPD', data, registrationName='VTPD') + elif grid.IsA('vtkPartitionedDataSetCollection'): + return CreateExtractor('VTPC', data, registrationName='VTPC') + elif grid.IsA('vtkHyperTreeGrid'): + return CreateExtractor('HTG', data, registrationName='HTG') + else: + raise RuntimeError("Unsupported data type: %s", grid.GetClassName()) + + +# Pipeline +data = TrivialProducer(registrationName=catalystChannel) + +# Returns extractor type based on data (or you can manually specify +extractor = create_extractor(data) + +# ------------------------------------------------------------------------------ +# Catalyst options +from paraview import catalyst +options = catalyst.Options() +options.ExtractsOutputDirectory = outputDirectory +options.GlobalTrigger.Frequency = frequency + +# ------------------------------------------------------------------------------ +if __name__ == '__main__': + from paraview.simple import SaveExtractsUsingCatalystOptions + # Code for non in-situ environments; if executing in post-processing + # i.e. non-Catalyst mode, let's generate extracts using Catalyst options + SaveExtractsUsingCatalystOptions(options) diff --git a/parse_isotime.hpp b/parse_isotime.hpp deleted file mode 100644 index a464803077e69b44153fc8f0f97cfa636dcf16cb..0000000000000000000000000000000000000000 --- a/parse_isotime.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#include <chrono> -#include <ctime> - -static std::chrono::time_point<std::chrono::system_clock> -parse_isotime(const std::string& iso8601) { - using namespace std; - tm t = {}; - // F: Equivalent to %Y-%m-%d, the ISO 8601 date format. - // T: ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S - // z: ISO 8601 offset from UTC in timezone (1 minute=1, 1 hour=100). If timezone cannot be determined, no characters - strptime(iso8601.c_str(), "%FT%T%z", &t); - return chrono::system_clock::from_time_t(mktime(&t)); -} diff --git a/pvExample.py b/pvExample.py index 627691590b661a9841660fcb556697fe0620df50..255ed2f525c8745aa7bf7934c454bcc1b9f2ce35 100644 --- a/pvExample.py +++ b/pvExample.py @@ -1,42 +1,29 @@ import os from paraview.simple import * -renderView1 = GetRenderView() - -producer = TrivialProducer(registrationName='domain1') - -display = Show(producer, renderView1) -if len(producer.PointData) > 0: - field_name = producer.PointData[0].GetName() - ColorBy(display, ('POINTS', field_name)) -else: - field_name = producer.CellData[0].GetName() - ColorBy(display, ('CELLS', field_name)) - -producer2 = TrivialProducer(registrationName='domain2') -display = Show(producer2, renderView1) -if len(producer2.PointData) > 0: - field_name = producer2.PointData[0].GetName() - ColorBy(display, ('POINTS', field_name)) -else: - field_name = producer2.CellData[0].GetName() - ColorBy(display, ('CELLS', field_name)) - -pNG1 = CreateExtractor('PNG', renderView1, registrationName='PNG1') -pNG1.Trigger = 'TimeStep' - -pNG1.Writer.FileName = 'RenderView1_{timestep:06d}{camera}.png' -pNG1.Writer.ImageResolution = [1920, 1080] -pNG1.Writer.Format = 'PNG' - # ------------------------------------------------------------------------------ # Catalyst options from paraview import catalyst options = catalyst.Options() options.GlobalTrigger = 'TimeStep' options.EnableCatalystLive = 1 +options.CatalystLiveURL = 'localhost:22222' options.CatalystLiveTrigger = 'TimeStep' +lonlat2sphere = '-1*sin(coordsX)*cos(coordsY)*iHat+cos(coordsX)*cos(coordsY)*jHat+sin(coordsY)*kHat' + +domain1 = TrivialProducer(registrationName='domain1') +calculator1 = Calculator(registrationName='Calculator1', Input=domain1) +calculator1.CoordinateResults = 1 +calculator1.Function = lonlat2sphere +calculator1Display = Show(calculator1) + +domain2 = TrivialProducer(registrationName='domain2') +calculator2 = Calculator(registrationName='Calculator2', Input=domain2) +calculator2.CoordinateResults = 1 +calculator2.Function = lonlat2sphere +calculator2Display = Show(calculator2) + # ------------------------------------------------------------------------------ if __name__ == '__main__': from paraview.simple import SaveExtractsUsingCatalystOptions