Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_STK_ExodusReaderFactory.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 
44 #include <Teuchos_TimeMonitor.hpp>
45 #include <PanzerAdaptersSTK_config.hpp>
46 
48 #include "Panzer_STK_Interface.hpp"
49 
50 #ifdef PANZER_HAVE_IOSS
51 
52 #include <Ionit_Initializer.h>
53 #include <Ioss_ElementBlock.h>
54 #include <Ioss_Region.h>
55 #include <GetBuckets.hpp>
56 #include <stk_io/StkMeshIoBroker.hpp>
57 #include <stk_io/IossBridge.hpp>
58 #include <stk_mesh/base/FieldParallel.hpp>
59 
60 #include "Teuchos_StandardParameterEntryValidators.hpp"
61 
62 namespace panzer_stk {
63 
64 STK_ExodusReaderFactory::STK_ExodusReaderFactory()
65  : fileName_(""), restartIndex_(0), userMeshScaling_(false), meshScaleFactor_(0.0)
66 { }
67 
68 STK_ExodusReaderFactory::STK_ExodusReaderFactory(const std::string & fileName,int restartIndex)
69  : fileName_(fileName), restartIndex_(restartIndex), userMeshScaling_(false), meshScaleFactor_(0.0)
70 { }
71 
72 Teuchos::RCP<STK_Interface> STK_ExodusReaderFactory::buildMesh(stk::ParallelMachine parallelMach) const
73 {
74  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::buildMesh()");
75 
76  using Teuchos::RCP;
77  using Teuchos::rcp;
78 
79  RCP<STK_Interface> mesh = buildUncommitedMesh(parallelMach);
80 
81  // in here you would add your fields...but it is better to use
82  // the two step construction
83 
84  // this calls commit on meta data
85  mesh->initialize(parallelMach,false);
86 
87  completeMeshConstruction(*mesh,parallelMach);
88 
89  return mesh;
90 }
91 
96 Teuchos::RCP<STK_Interface> STK_ExodusReaderFactory::buildUncommitedMesh(stk::ParallelMachine parallelMach) const
97 {
98  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::buildUncomittedMesh()");
99 
100  using Teuchos::RCP;
101  using Teuchos::rcp;
102 
103  // read in meta data
104  stk::io::StkMeshIoBroker* meshData = new stk::io::StkMeshIoBroker(parallelMach);
105  meshData->property_add(Ioss::Property("LOWER_CASE_VARIABLE_NAMES", false));
106  meshData->add_mesh_database(fileName_, "exodusII", stk::io::READ_MESH);
107  meshData->create_input_mesh();
108  RCP<stk::mesh::MetaData> metaData = meshData->meta_data_rcp();
109 
110  // add in "FAMILY_TREE" entity for doing refinement
111  RCP<STK_Interface> mesh = rcp(new STK_Interface(metaData));
112  mesh->initializeFromMetaData();
113  mesh->instantiateBulkData(parallelMach);
114  meshData->set_bulk_data(mesh->getBulkData());
115 
116  // read in other transient fields, these will be useful later when
117  // trying to read other fields for use in solve
118  meshData->add_all_mesh_fields_as_input_fields();
119 
120  // store mesh data pointer for later use in initializing
121  // bulk data
122  mesh->getMetaData()->declare_attribute_with_delete(meshData);
123 
124  // build element blocks
125  registerElementBlocks(*mesh,*meshData);
126  registerSidesets(*mesh);
127  registerNodesets(*mesh);
128 
129  mesh->addPeriodicBCs(periodicBCVec_);
130 
131  return mesh;
132 }
133 
134 void STK_ExodusReaderFactory::completeMeshConstruction(STK_Interface & mesh,stk::ParallelMachine parallelMach) const
135 {
136  PANZER_FUNC_TIME_MONITOR("panzer::STK_ExodusReaderFactory::completeMeshConstruction()");
137 
138  using Teuchos::RCP;
139  using Teuchos::rcp;
140 
141  if(not mesh.isInitialized())
142  mesh.initialize(parallelMach);
143 
144  // grab mesh data pointer to build the bulk data
145  stk::mesh::MetaData & metaData = *mesh.getMetaData();
146  stk::mesh::BulkData & bulkData = *mesh.getBulkData();
147  stk::io::StkMeshIoBroker * meshData =
148  const_cast<stk::io::StkMeshIoBroker *>(metaData.get_attribute<stk::io::StkMeshIoBroker>());
149  // if const_cast is wrong ... why does it feel so right?
150  // I believe this is safe since we are basically hiding this object under the covers
151  // until the mesh construction can be completed...below I cleanup the object myself.
152  TEUCHOS_ASSERT(metaData.remove_attribute(meshData));
153  // remove the MeshData attribute
154 
155  // build mesh bulk data
156  meshData->populate_bulk_data();
157 
158  // The following section of code is applicable if mesh scaling is
159  // turned on from the input file.
160  if (userMeshScaling_)
161  {
162  stk::mesh::Field<double,stk::mesh::Cartesian>* coord_field =
163  metaData.get_field<stk::mesh::Field<double, stk::mesh::Cartesian> >(stk::topology::NODE_RANK, "coordinates");
164 
165  stk::mesh::Selector select_all_local = metaData.locally_owned_part() | metaData.globally_shared_part();
166  stk::mesh::BucketVector const& my_node_buckets = bulkData.get_buckets(stk::topology::NODE_RANK, select_all_local);
167 
168  int mesh_dim = mesh.getDimension();
169 
170  // Scale the mesh
171  const double inv_msf = 1.0/meshScaleFactor_;
172  for (size_t i=0; i < my_node_buckets.size(); ++i)
173  {
174  stk::mesh::Bucket& b = *(my_node_buckets[i]);
175  double* coordinate_data = field_data( *coord_field, b );
176 
177  for (size_t j=0; j < b.size(); ++j) {
178  for (int k=0; k < mesh_dim; ++k) {
179  coordinate_data[mesh_dim*j + k] *= inv_msf;
180  }
181  }
182  }
183  }
184 
185  // put in a negative index and (like python) the restart will be from the back
186  // (-1 is the last time step)
187  int restartIndex = restartIndex_;
188  if(restartIndex<0) {
189  std::pair<int,double> lastTimeStep = meshData->get_input_io_region()->get_max_time();
190  restartIndex = 1+restartIndex+lastTimeStep.first;
191  }
192 
193  // populate mesh fields with specific index
194  meshData->read_defined_input_fields(restartIndex);
195 
196  mesh.buildSubcells();
197  mesh.buildLocalElementIDs();
198 
199  if (userMeshScaling_) {
200  stk::mesh::Field<double,stk::mesh::Cartesian>* coord_field =
201  metaData.get_field<stk::mesh::Field<double, stk::mesh::Cartesian> >(stk::topology::NODE_RANK, "coordinates");
202  std::vector< const stk::mesh::FieldBase *> fields;
203  fields.push_back(coord_field);
204 
205  stk::mesh::communicate_field_data(bulkData, fields);
206  }
207 
208  if(restartIndex>0) // process_input_request is a no-op if restartIndex<=0 ... thus there would be no inital time
209  mesh.setInitialStateTime(meshData->get_input_io_region()->get_state_time(restartIndex));
210  else
211  mesh.setInitialStateTime(0.0); // no initial time to speak, might as well use 0.0
212 
213  // clean up mesh data object
214  delete meshData;
215 
216  // calls Stk_MeshFactory::rebalance
217  this->rebalance(mesh);
218 }
219 
221 void STK_ExodusReaderFactory::setParameterList(const Teuchos::RCP<Teuchos::ParameterList> & paramList)
222 {
223  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(!paramList->isParameter("File Name"),
225  "Error, the parameter {name=\"File Name\","
226  "type=\"string\""
227  "\nis required in parameter (sub)list \""<< paramList->name() <<"\"."
228  "\n\nThe parsed parameter parameter list is: \n" << paramList->currentParametersString()
229  );
230 
231  // Set default values here. Not all the params should be set so this
232  // has to be done manually as opposed to using
233  // validateParametersAndSetDefaults().
234  if(!paramList->isParameter("Restart Index"))
235  paramList->set<int>("Restart Index", -1);
236 
237  if(!paramList->isSublist("Periodic BCs"))
238  paramList->sublist("Periodic BCs");
239 
240  Teuchos::ParameterList& p_bcs = paramList->sublist("Periodic BCs");
241  if (!p_bcs.isParameter("Count"))
242  p_bcs.set<int>("Count", 0);
243 
244  paramList->validateParameters(*getValidParameters(),0);
245 
246  setMyParamList(paramList);
247 
248  fileName_ = paramList->get<std::string>("File Name");
249 
250  restartIndex_ = paramList->get<int>("Restart Index");
251 
252  // get any mesh scale factor
253  if (paramList->isParameter("Scale Factor"))
254  {
255  meshScaleFactor_ = paramList->get<double>("Scale Factor");
256  userMeshScaling_ = true;
257  }
258 
259  // read in periodic boundary conditions
260  parsePeriodicBCList(Teuchos::rcpFromRef(paramList->sublist("Periodic BCs")),periodicBCVec_);
261 }
262 
264 Teuchos::RCP<const Teuchos::ParameterList> STK_ExodusReaderFactory::getValidParameters() const
265 {
266  static Teuchos::RCP<Teuchos::ParameterList> validParams;
267 
268  if(validParams==Teuchos::null) {
269  validParams = Teuchos::rcp(new Teuchos::ParameterList);
270  validParams->set<std::string>("File Name","<file name not set>","Name of exodus file to be read",
272 
273  validParams->set<int>("Restart Index",-1,"Index of solution to read in",
274  Teuchos::rcp(new Teuchos::AnyNumberParameterEntryValidator(Teuchos::AnyNumberParameterEntryValidator::PREFER_INT,Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes(true))));
275 
276  validParams->set<double>("Scale Factor", 1.0, "Scale factor to apply to mesh after read",
277  Teuchos::rcp(new Teuchos::AnyNumberParameterEntryValidator(Teuchos::AnyNumberParameterEntryValidator::PREFER_DOUBLE,Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes(true))));
278 
279  Teuchos::ParameterList & bcs = validParams->sublist("Periodic BCs");
280  bcs.set<int>("Count",0); // no default periodic boundary conditions
281  }
282 
283  return validParams.getConst();
284 }
285 
286 void STK_ExodusReaderFactory::registerElementBlocks(STK_Interface & mesh,stk::io::StkMeshIoBroker & meshData) const
287 {
288  using Teuchos::RCP;
289 
290  RCP<stk::mesh::MetaData> femMetaData = mesh.getMetaData();
291 
292  // here we use the Ioss interface because they don't add
293  // "bonus" element blocks and its easier to determine
294  // "real" element blocks versus STK-only blocks
295  const Ioss::ElementBlockContainer & elem_blocks = meshData.get_input_io_region()->get_element_blocks();
296  for(Ioss::ElementBlockContainer::const_iterator itr=elem_blocks.begin();itr!=elem_blocks.end();++itr) {
297  Ioss::GroupingEntity * entity = *itr;
298  const std::string & name = entity->name();
299 
300  const stk::mesh::Part * part = femMetaData->get_part(name);
301  const CellTopologyData * ct = femMetaData->get_cell_topology(*part).getCellTopologyData();
302 
303  TEUCHOS_ASSERT(ct!=0);
304  mesh.addElementBlock(part->name(),ct);
305  }
306 }
307 
308 template <typename SetType>
309 void buildSetNames(const SetType & setData,std::vector<std::string> & names)
310 {
311  // pull out all names for this set
312  for(typename SetType::const_iterator itr=setData.begin();itr!=setData.end();++itr) {
313  Ioss::GroupingEntity * entity = *itr;
314  names.push_back(entity->name());
315  }
316 }
317 
318 void STK_ExodusReaderFactory::registerSidesets(STK_Interface & mesh) const
319 {
320  using Teuchos::RCP;
321 
322  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
323  const stk::mesh::PartVector & parts = metaData->get_parts();
324 
325  stk::mesh::PartVector::const_iterator partItr;
326  for(partItr=parts.begin();partItr!=parts.end();++partItr) {
327  const stk::mesh::Part * part = *partItr;
328  const stk::mesh::PartVector & subsets = part->subsets();
329  // const CellTopologyData * ct = stk::mesh::get_cell_topology(*part).getCellTopologyData();
330  const CellTopologyData * ct = metaData->get_cell_topology(*part).getCellTopologyData();
331 
332  // if a side part ==> this is a sideset: now storage is recursive
333  // on part contains all sub parts with consistent topology
334  if(part->primary_entity_rank()==mesh.getSideRank() && ct==0 && subsets.size()>0) {
335  TEUCHOS_TEST_FOR_EXCEPTION(subsets.size()!=1,std::runtime_error,
336  "STK_ExodusReaderFactory::registerSidesets error - part \"" << part->name() <<
337  "\" has more than one subset");
338 
339  // grab cell topology and name of subset part
340  const stk::mesh::Part * ss_part = subsets[0];
341  // const CellTopologyData * ss_ct = stk::mesh::get_cell_topology(*ss_part).getCellTopologyData();
342  const CellTopologyData * ss_ct = metaData->get_cell_topology(*ss_part).getCellTopologyData();
343 
344  // only add subset parts that have no topology
345  if(ss_ct!=0)
346  mesh.addSideset(part->name(),ss_ct);
347  }
348  }
349 }
350 
351 void STK_ExodusReaderFactory::registerNodesets(STK_Interface & mesh) const
352 {
353  using Teuchos::RCP;
354 
355  RCP<stk::mesh::MetaData> metaData = mesh.getMetaData();
356  const stk::mesh::PartVector & parts = metaData->get_parts();
357 
358  stk::mesh::PartVector::const_iterator partItr;
359  for(partItr=parts.begin();partItr!=parts.end();++partItr) {
360  const stk::mesh::Part * part = *partItr;
361  const CellTopologyData * ct = metaData->get_cell_topology(*part).getCellTopologyData();
362 
363  // if a side part ==> this is a sideset: now storage is recursive
364  // on part contains all sub parts with consistent topology
365  if(part->primary_entity_rank()==mesh.getNodeRank() && ct==0) {
366 
367  // only add subset parts that have no topology
368  if(part->name()!=STK_Interface::nodesString)
369  mesh.addNodeset(part->name());
370  }
371  }
372 }
373 
374 }
375 
376 #endif
RCP< const T > getConst() const
const std::string & name() const
std::string currentParametersString() const
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static const std::string nodesString
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool isSublist(const std::string &name) const
void validateParameters(ParameterList const &validParamList, int const depth=1000, EValidateUsed const validateUsed=VALIDATE_USED_ENABLED, EValidateDefaults const validateDefaults=VALIDATE_DEFAULTS_ENABLED) const
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(throw_exception_test, Exception, msg)