Commit 627cad74 authored by Robert Maynard's avatar Robert Maynard
Browse files

Merge branch 'release-v1' into 'release-v1'

Update release-v1 to contain updates to smtk::mesh

Need to update release-v1 to get the latest and greatest mesh code.

See merge request !12
parents dc837125 cc1795c1
......@@ -79,6 +79,8 @@ mark_as_advanced(
LIBRARY_OUTPUT_PATH
)
include(CMakeDependentOption)
################################################################################
# Options that the user controls
################################################################################
......@@ -87,32 +89,30 @@ option(SMTK_NO_SYSTEM_BOOST "Allow boost to search for system installed boost" O
# Option to build Qt ui compoments for attributes
option(SMTK_ENABLE_TESTING "Enable Testing" ON)
option(SMTK_ENABLE_PYTHON_WRAPPING "Build Python Wrappings using Shiboken" OFF)
if (SMTK_ENABLE_PYTHON_WRAPPING)
# Provide system packagers with the ability to install SMTK
# to the system's Python site package directory. The default
# is off so that people building relocatable bundles (such as
# CMB) can distribute their own Python interpreter with
# internal packages (e.g., as part of a Mac ".app" bundle).
option(
SMTK_INSTALL_PYTHON_TO_SITE_PACKAGES
"Install Python modules to the interpreter's site-packages directory or into CMAKE_INSTALL_PREFIX?"
OFF)
mark_as_advanced(SMTK_INSTALL_PYTHON_TO_SITE_PACKAGES)
endif()
# Provide system packagers with the ability to install SMTK
# to the system's Python site package directory. The default
# is off so that people building relocatable bundles (such as
# CMB) can distribute their own Python interpreter with
# internal packages (e.g., as part of a Mac ".app" bundle).
cmake_dependent_option(
SMTK_INSTALL_PYTHON_TO_SITE_PACKAGES
"Install Python modules to the interpreter's site-packages directory or into CMAKE_INSTALL_PREFIX?"
OFF
SMTK_ENABLE_PYTHON_WRAPPING OFF)
mark_as_advanced(SMTK_INSTALL_PYTHON_TO_SITE_PACKAGES)
option(SMTK_ENABLE_QT_SUPPORT "Build Qt GUI" OFF)
option(SMTK_ENABLE_VTK_SUPPORT "Build VTK component" OFF)
option(SMTK_ENABLE_REMUS_SUPPORT "Build Remus components" OFF)
option(SMTK_ENABLE_PARAVIEW_SUPPORT "Build paraview plugins for model sessions" OFF)
cmake_dependent_option(SMTK_ENABLE_PARAVIEW_SUPPORT "Build paraview plugins for model sessions" OFF
SMTK_ENABLE_VTK_SUPPORT OFF)
option(SMTK_ENABLE_CGM_SESSION "Build CGM component" OFF)
option(SMTK_ENABLE_DISCRETE_SESSION "Build discrete model session components" OFF)
option(SMTK_ENABLE_POLYGON_SESSION "Build Boost.polygon model session." ON)
if (SMTK_ENABLE_VTK_SUPPORT)
option(SMTK_ENABLE_EXODUS_SESSION "Build a session to Exodus-II side sets" ON)
endif()
if (SMTK_ENABLE_REMUS_SUPPORT)
option(SMTK_ENABLE_REMOTE_SESSION "Build a session that allows modeling in a remote process." ON)
endif()
cmake_dependent_option(SMTK_ENABLE_EXODUS_SESSION "Build a session to Exodus-II side sets" ON
SMTK_ENABLE_VTK_SUPPORT OFF)
cmake_dependent_option(SMTK_ENABLE_REMOTE_SESSION "Build a session that allows modeling in a remote process" ON
SMTK_ENABLE_REMUS_SUPPORT OFF)
option(SMTK_USE_SYSTEM_MOAB "Use the system-installed moab?" OFF)
option(SMTK_USE_SYSTEM_SPARSEHASH "Use the system-installed sparsehash?" OFF)
......
.. _smtk-contributing:
********************
Contributing to SMTK
********************
......@@ -5,6 +7,9 @@ Contributing to SMTK
.. role:: cxx(code)
:language: c++
.. role:: cmake(code)
:language: cmake
.. contents::
The first step to contributing to SMTK is to obtain the source code and build it.
......@@ -31,6 +36,7 @@ With that in mind:
* common — source for classes used throughout the smtkCore library
* attribute — source for :ref:`smtk-attribute-sys` in the smtkCore library
* model — source for :ref:`smtk-model-sys` in the smtkCore library
* mesh — source for :ref:`smtk-mesh-sys` in the smtkCore library
* simulation — aids to exporting simulation input decks in the smtkCore library
* io — file and string I/O in the smtkCore library, a mix of XML and JSON
* view — source for providing views of attributes and models in the smtkCore library
......@@ -66,9 +72,15 @@ Code style
Using SMTK from another project
===============================
.. todo::
SMTK generates a file named :file:`SMTKConfig.cmake` that allows other projects to find and use SMTK.
This file is installed to :file:`${CMAKE_INSTALL_PREFIX}/lib/cmake/SMTK/`.
Your project can add SMTK with
.. code:: cmake
find_package(SMTK)
SMTK does not currently export an SMTKConfig.cmake file like it should.
Then, when building your project, set CMake's :cmake:`SMTK_DIR` to the directory containing :file:`SMTKConfig.cmake`.
Extending SMTK
==============
......
......@@ -35,13 +35,20 @@ SMTK, clone the repository:
.. code:: sh
git clone git://public.kitware.com/SMTK.git
git clone https://gitlab.kitware.com/cmb/smtk.git
and follow the instructions in the :file:`ReadMe.mkd` file
in the top-level source directory.
The rest of this user's guide assumes you have built
and installed SMTK according to these instructions.
In addition to cloning anonymously as mentioned above,
you are also welcome to create an account on either
gitlab.kitware.com or github.com and fork the repository.
Forking the repository will allow you to submit contributions
back to SMTK for inclusion in later releases.
See :ref:`smtk-contributing` for more on how to
prepare and submit changes to SMTK.
.. toctree::
:maxdepth: 4
......
==
IO
============
==
:smtk:io:`WriteMesh <smtk::io::WriteMesh>`
:smtk:`WriteMesh <smtk::io::WriteMesh>`
Writes out a given :smtk:`Collection <smtk::mesh::Collection>`, or only
the elements that match a given Domain, Neumann, or Dirichlet property.
......@@ -10,7 +11,7 @@ IO
+ Exodus II (exo exoII exo2 g gen)
:smtk:io:`ImportMesh <smtk::io::ImportMesh>`
:smtk:`ImportMesh <smtk::io::ImportMesh>`
Load a given file in as a new :smtk:`Collection <smtk::mesh::Collection>` or
part of an existing :smtk:`Collection <smtk::mesh::Collection>`. Also
supports loading just elements that a given Domain, Neumann, or Dirichlet
......@@ -23,11 +24,11 @@ IO
Serialization
============
:smtk:io:`ExportJSON <smtk::io::ExportJSON>`
:smtk:`ExportJSON <smtk::io::ExportJSON>`
Export all the :smtk:`Collection <smtk::mesh::Collection>` that have
associations with the any model that is part of the passed in
:smtk:`Manager <smtk::model::Manager>`. The exporter will save each
Collection using :smtk:io:`WriteMesh <smtk::io::WriteMesh>` with the file
Collection using :smtk:`WriteMesh <smtk::io::WriteMesh>` with the file
type MOAB and extension h5m.
The format of the created json is:
......@@ -106,7 +107,7 @@ Serialization
}
:smtk:io:`ImportJSON <smtk::io::ImportJSON>`
:smtk:`ImportJSON <smtk::io::ImportJSON>`
Imports all the :smtk:`Collection <smtk::mesh::Collection>` that are listed
in the provided JSON string. Each Collection will be marked as being associated
with the provided model :smtk:`Manager <smtk::model::Manager>`.
......@@ -13,3 +13,4 @@ entity.
:maxdepth: 3
concepts.rst
IO.rst
......@@ -928,12 +928,22 @@ void QEntityItemModel::updateChildPhrases(
for (smtk::model::DescriptivePhrases::iterator it = origSubs.begin();
it != origSubs.end(); ++it, ++remIdx)
{
EntityRef related = (*it)->relatedEntity();
found = false;
EntityRef related = (*it)->relatedEntity();
for (smtk::model::DescriptivePhrases::iterator nit = newSubs.begin();
nit != newSubs.end(); ++nit)
{
if(related == (*nit)->relatedEntity())
if((*it)->phraseType() != (*nit)->phraseType())
continue;
if( // mesh phrases
((*it)->phraseType() == MESH_SUMMARY &&
(((*it)->relatedMeshCollection() &&
(*it)->relatedMeshCollection()->entity() == (*nit)->relatedMeshCollection()->entity()) ||
(!(*it)->relatedMesh().is_empty() && (*it)->relatedMesh() == (*nit)->relatedMesh())))
||
// model phrases
((*it)->phraseType() != MESH_SUMMARY && related == (*nit)->relatedEntity())
)
{
found = true;
break;
......@@ -950,7 +960,18 @@ void QEntityItemModel::updateChildPhrases(
for (smtk::model::DescriptivePhrases::iterator it = newSubs.begin();
it != newSubs.end(); ++it, ++newIdx)
{
int origId = phrase->argFindChild((*it)->relatedEntity());
int origId = -1;
if((*it)->phraseType() == MESH_SUMMARY)
{
if((*it)->relatedMeshCollection())
origId = phrase->argFindChild((*it)->relatedMeshCollection());
else
origId = phrase->argFindChild((*it)->relatedMesh());
}
else
{
origId = phrase->argFindChild((*it)->relatedEntity());
}
if( origId < 0 )
newDphrs.push_back(std::make_pair(*it, newIdx));
}
......
......@@ -4,9 +4,10 @@ smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/MeshOperator.sbt" remusOperatorXM
add_library(smtkRemusExt ${remusExtSource})
target_link_libraries(smtkRemusExt
PRIVATE
LINK_PRIVATE
RemusClient
smtkCore
${Boost_LIBRARIES}
)
target_include_directories(smtkRemusExt PRIVATE ${REMUS_INCLUDE_DIRS})
......
......@@ -18,6 +18,9 @@
#include "smtk/model/Manager.h"
#include "smtk/model/Model.h"
#include "smtk/mesh/Manager.h"
#include "smtk/mesh/Collection.h"
#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/ModelEntityItem.h"
#include "smtk/attribute/StringItem.h"
......@@ -26,6 +29,12 @@
#include "smtk/io/ExportJSON.txx"
#include "smtk/io/ImportJSON.h"
//todo: remove this once remus supports automatic transfer of FileHandles
// and Destructive Read of FileHandles
//force to use filesystem version 3
#define BOOST_FILESYSTEM_VERSION 3
#include <boost/filesystem.hpp>
//todo: remove this once remus Issue #183 has been resolved.
// #include <boost/date_time/posix_time/posix_time.hpp>
// #include <boost/thread/thread.hpp>
......@@ -148,31 +157,59 @@ OperatorResult MeshOperator::operateInternal()
if(haveResultFromWorker)
{
//now fetch the latest results from the server
remus::proto::JobResult updatedModel = client.retrieveResults(job);
remus::proto::JobResult meshMetaData = client.retrieveResults(job);
smtk::mesh::ManagerPtr meshManager = this->manager()->meshes();
//parse the job result as a json string
smtk::io::ImportJSON::intoModelManager(updatedModel.data(), this->manager());
//determine all existing collection
typedef std::map< smtk::common::UUID, smtk::mesh::CollectionPtr > CollectionStorage;
CollectionStorage existingCollections(meshManager->collectionBegin(),
meshManager->collectionEnd());
cJSON* root = cJSON_Parse(updatedModel.data());
//parse the job result as json mesh data
cJSON* root = cJSON_Parse(meshMetaData.data());
smtk::io::ImportJSON::ofMeshesOfModel(root, this->manager());
cJSON_Delete(root);
// Now set or increment the SMTK_MESH_GEN_PROP property for the models
// The client can use this property to check if there is an analysis mesh created
// for the model
smtk::model::Models::iterator it;
for (it = models.begin(); it != models.end(); ++it)
//
//iterate over all collections looking for new collections. When we find
//a new mesh collection, we will delete the file that was used to generate
//that collection, as that file is meant to be temporary and only exist
//for data transfer back from the worker.
//
//This all should be removed, and instead remus should handle all this logic
//
//
//
for(smtk::mesh::Manager::const_iterator i = meshManager->collectionBegin();
i != meshManager->collectionEnd();
++i)
{
smtk::mesh::CollectionPtr collection = i->second;
smtk::common::UUID collectionUUID = i->first;
if( existingCollections.find(collectionUUID) == existingCollections.end())
{ //found a new collection
std::string location = collection->readLocation();
if(!location.empty())
{ //delete the file if it exists
::boost::filesystem::path cpath( location );
::boost::filesystem::remove( cpath );
}
collection->clearReadWriteLocations();
}
}
//mark all models and submodels as modified
smtk::model::Models allModels = models;
for(smtk::model::Models::const_iterator m = models.begin();
m != models.end();
++m)
{
IntegerList& gen(this->manager()->integerProperty(it->entity(), SMTK_MESH_GEN_PROP));
if (gen.empty())
gen.push_back(0);
else
++gen[0];
smtk::model::Models submodels = m->submodels();
allModels.insert(allModels.end(), submodels.begin(), submodels.end());
}
this->addEntitiesToResult(result, allModels, MODIFIED);
//current question is how do we know how to mark the tessellations
//of the model as modified?
this->addEntitiesToResult(result, models, MODIFIED);
result->findModelEntity("mesh_created")->setValues(models.begin(), models.end());
}
return result;
......
......@@ -979,7 +979,7 @@ private:
};
}
/**\brief Serialize a single mesh colelction
/**\brief Serialize a single mesh collection
*
*/
int ExportJSON::forSingleCollection(cJSON* mdesc,
......@@ -991,6 +991,7 @@ int ExportJSON::forSingleCollection(cJSON* mdesc,
cJSON_AddItemToObject(mdesc, collectionUUID.c_str(), jsonCollection);
cJSON_AddItemToObject(jsonCollection,"formatVersion", cJSON_CreateNumber(1));
cJSON_AddStringToObject(jsonCollection,"name", collection->name().c_str());
//assoicated model uuid of the collection
if(!collection->associatedModel().isNull())
......
......@@ -1146,7 +1146,13 @@ int ImportJSON::ofMeshesOfModel(cJSON* node,
//remove the old collection, as its interface is now owned by the new
//collection
meshMgr->removeCollection(importedCollection);
importedCollection.reset();
//We need to set the read location on the orginal collection if
//the interface is moab
if(isValidMoab)
{
collection->readLocation( importedCollection->readLocation() );
}
//set the name back to the collection
cJSON* collecNameNode = cJSON_GetObjectItem(child, "name");
......@@ -1154,6 +1160,11 @@ int ImportJSON::ofMeshesOfModel(cJSON* node,
cJSON_GetStringValue(collecNameNode, collectionName);
collection->name(collectionName);
//ask the manager to generate a unique name for the collection, if it
//doesn't already have a unique name. This occurs when meshes have
//no name, or a name that has already been used
collection->assignUniqueNameIfNotAlready();
//set the collections model manager so that we can do model based
//queries properly
collection->setModelManager( modelMgr );
......
......@@ -27,6 +27,19 @@ if (SMTK_DATA_DIR AND EXISTS ${SMTK_DATA_DIR}/ReadMe.mkd)
)
endforeach()
set(reader_test attributeReaderTest)
add_test(${reader_test}Py
${PYTHON_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/${reader_test}.py
${SMTK_DATA_DIR}/smtk/attribute/resourceTest/ShallowWater2D.sbi
29
19
)
set_tests_properties(${reader_test}Py
PROPERTIES
ENVIRONMENT "PYTHONPATH=${VTKPY_DIR}${SHIBOKEN_SMTK_PYTHON};${LIB_ENV_VAR}"
)
set(reader_test ResourceSetReaderTest)
add_test(${reader_test}Py
${PYTHON_EXECUTABLE}
......
#!/usr/bin/python
import sys
#=============================================================================
#
# Copyright (c) Kitware, Inc.
# All rights reserved.
# See LICENSE.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even
# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the above copyright notice for more information.
#
#=============================================================================
import smtk
from smtk.simple import *
class TestAttributeReader():
"""A test for AttributeReader"""
def setUp(self):
if len(sys.argv) < 2:
print "Reads attribute system file"
print "Usage: AttributeReaderTest attribute_file"
print " [expect_number_of_definitions]"
print " [expect_number_of_attributes]"
return 1
self.status = 0 # return value
self.attsys = smtk.attribute.System()
self.reader = smtk.io.AttributeReader()
self.logger = smtk.io.Logger()
input_path = sys.argv[1]
hasErrors = self.reader.read(self.attsys, input_path, self.logger)
if hasErrors:
print "Reader has errors"
print self.logger.convertToString()
self.status = self.status + 1
def testSimpleRead(self):
# Test definition count
if len(sys.argv) <= 2:
return 1
expectedDefinitionCount = 0
convert = sys.argv[2]
try:
expectedDefinitionCount = int(convert)
except:
self.status = self.status + 1
finally:
if expectedDefinitionCount < 0:
print "ERROR: argv[2] not an unsigned integer"
self.status = self.status + 1
else:
definitionList = self.attsys.definitions()
if len(definitionList) != expectedDefinitionCount:
print "ERROR: Expecting ", expectedDefinitionCount, \
" definitions, loaded ", len(definitionList)
self.status = self.status + 1
else:
print "Number of definitions loaded:", len(definitionList)
#for i,defn in enumerate(definitionList):
# print i, defn.type(), defn.isAbstract()
# Test attribute count
if len(sys.argv) <= 3:
return self.status
expectedAttributeCount = 0
convert = sys.argv[3]
try:
expectedAttributeCount = int(convert)
except:
self.status = self.status + 1
finally:
if expectedAttributeCount < 0:
print "ERROR: argv[2] not an unsigned integer"
self.status = self.status + 1
else:
attributeList = self.attsys.attributes()
if len(attributeList) != expectedAttributeCount:
print "ERROR: Expecting ", expectedAttributeCount, \
" attributes, loaded ", len(attributeList)
self.status = self.status + 1
else:
print "Number of attributes loaded:", len(attributeList)
#for i,att in enumerate(attributeList):
# print i, att.name()
return self.status
if __name__ == '__main__':
t = TestAttributeReader()
t.setUp()
sys.exit(t.testSimpleRead())
......@@ -152,6 +152,17 @@ void Collection::name(const std::string& n)
this->m_name = n;
}
//----------------------------------------------------------------------------
bool Collection::assignUniqueNameIfNotAlready()
{
smtk::mesh::ManagerPtr currentManager = this->m_internals->manager();
if(currentManager)
{ //if we are associated with a valid manager
return currentManager->assignUniqueName( this->shared_from_this() );
}
return false;
}
//----------------------------------------------------------------------------
const std::string& Collection::readLocation() const
{
......@@ -181,6 +192,14 @@ void Collection::writeLocation(const std::string& n)
this->m_writeLocation = n;
}
//----------------------------------------------------------------------------
void Collection::clearReadWriteLocations()
{
this->m_readLocation.clear();
this->m_writeLocation.clear();
}
//----------------------------------------------------------------------------
std::string Collection::interfaceName() const
{
......
......@@ -73,6 +73,14 @@ public:
const std::string& name() const;
void name(const std::string& n);
//assign the collection a unique name, given the current manager.
//Note:
//If the current name is already unique, no change will happen but we will
//return true.
//If the collection has no manager, the current name is not changed, and
//false is returned
bool assignUniqueNameIfNotAlready();
//get the file that this collection was created from
//will return an empty string if this collection wasn't read from file
const std::string& readLocation() const;
......@@ -82,6 +90,11 @@ public:
void writeLocation(const std::string& path);
const std::string& writeLocation() const;
//clear both the read and write locations for the collection. This
//is generally done when de-serializing a collection and the read and write
//locations are going to be deleted by the calling code.
void clearReadWriteLocations();
//get a string the identifies the interface type of the collection
// valid types are:
// "moab"
......@@ -268,6 +281,7 @@ private:
friend class smtk::mesh::Manager;
friend class smtk::io::ImportMesh;
friend class smtk::io::ImportJSON;
//called by the manager that manages this collection, means that somebody
//has requested us to be removed from a collection
......
......@@ -13,7 +13,10 @@
#include "smtk/common/UUID.h"
#include <boost/lexical_cast.hpp>
#include <map>
#include <set>
namespace smtk {
namespace mesh {
......@@ -99,10 +102,40 @@ private:
ContainerType Collections;
};
//----------------------------------------------------------------------------
class Manager::InternalNameGeneratorImpl
{
public:
InternalNameGeneratorImpl():
m_value(1),
m_basename("Mesh_")
{
}
std::string next( const std::set< std::string >& usedNames )
{
std::string result(this->m_basename);
result += boost::lexical_cast< std::string >(this->m_value++);
while( usedNames.find(result) != usedNames.end() )
{
result = (std::string(this->m_basename) += boost::lexical_cast< std::string >(this->m_value++));
}
std::cout << "generating name: " << result << std::endl;
return result;
}
private:
int m_value;
std::string m_basename;
};
//----------------------------------------------------------------------------
Manager::Manager():
m_collector( new InternalStorageImpl() ),
m_nameGenerator( new InternalNameGeneratorImpl() ),
m_uuidGenerator()
{
......@@ -295,5 +328,39 @@ Manager::associatedCollectionIds( const smtk::model::EntityRef& eref) const