Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_STK_SquareQuadMeshFactory.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 
44 #include <Teuchos_TimeMonitor.hpp>
45 #include <PanzerAdaptersSTK_config.hpp>
46 
47 // #define ENABLE_UNIFORM
48 
49 using Teuchos::RCP;
50 using Teuchos::rcp;
51 
52 namespace panzer_stk {
53 
55 {
57 }
58 
61 {
62 }
63 
65 Teuchos::RCP<STK_Interface> SquareQuadMeshFactory::buildMesh(stk::ParallelMachine parallelMach) const
66 {
67  PANZER_FUNC_TIME_MONITOR("panzer::SquareQuadMeshFactory::buildMesh()");
68 
69  // build all meta data
70  RCP<STK_Interface> mesh = buildUncommitedMesh(parallelMach);
71 
72  // commit meta data
73  mesh->initialize(parallelMach);
74 
75  // build bulk data
76  completeMeshConstruction(*mesh,parallelMach);
77 
78  return mesh;
79 }
80 
82 {
83  PANZER_FUNC_TIME_MONITOR("panzer::SquareQuadMeshFactory::buildUncomittedMesh()");
84 
85  RCP<STK_Interface> mesh = rcp(new STK_Interface(2));
86 
87  machRank_ = stk::parallel_machine_rank(parallelMach);
88  machSize_ = stk::parallel_machine_size(parallelMach);
89 
90  if (xProcs_ == -1 && yProcs_ == -1) {
91  // copied from galeri
92  xProcs_ = yProcs_ = Teuchos::as<int>(pow(Teuchos::as<double>(machSize_), 0.5));
93 
94  if (xProcs_ * yProcs_ != Teuchos::as<int>(machSize_)) {
95  // Simple method to find a set of processor assignments
96  xProcs_ = yProcs_ = 1;
97 
98  // This means that this works correctly up to about maxFactor^2
99  // processors.
100  const int maxFactor = 100;
101 
102  int ProcTemp = machSize_;
103  int factors[maxFactor];
104  for (int jj = 0; jj < maxFactor; jj++) factors[jj] = 0;
105  for (int jj = 2; jj < maxFactor; jj++) {
106  bool flag = true;
107  while (flag) {
108  int temp = ProcTemp/jj;
109  if (temp*jj == ProcTemp) {
110  factors[jj]++;
111  ProcTemp = temp;
112 
113  } else {
114  flag = false;
115  }
116  }
117  }
118  xProcs_ = ProcTemp;
119  for (int jj = maxFactor-1; jj > 0; jj--) {
120  while (factors[jj] != 0) {
121  if (xProcs_ <= yProcs_) xProcs_ = xProcs_*jj;
122  else yProcs_ = yProcs_*jj;
123  factors[jj]--;
124  }
125  }
126  }
127 
128  } else if(xProcs_==-1) {
129  // default x only decomposition
130  xProcs_ = machSize_;
131  yProcs_ = 1;
132  }
133  TEUCHOS_TEST_FOR_EXCEPTION(int(machSize_) != xProcs_ * yProcs_, std::logic_error,
134  "Cannot build SquareQuadMeshFactory. The product of 'X Procs * Y Procs = " << xProcs_ << "*" << yProcs_ << " = " << xProcs_*yProcs_
135  << "' must equal the number of processors = " << machSize_
136  << "\n\n\t==> Run the simulation with an appropriate number of processors, i.e. #procs = " << xProcs_*yProcs_ << ".\n");
138 
139  // build meta information: blocks and side set setups
140  buildMetaData(parallelMach,*mesh);
141 
142  mesh->addPeriodicBCs(periodicBCVec_);
143 
144  return mesh;
145 }
146 
147 void SquareQuadMeshFactory::completeMeshConstruction(STK_Interface & mesh,stk::ParallelMachine parallelMach) const
148 {
149  PANZER_FUNC_TIME_MONITOR("panzer::SquareQuadMeshFactory::completeMeshConstruction()");
150 
151  if(not mesh.isInitialized())
152  mesh.initialize(parallelMach);
153 
154  // add node and element information
155  buildElements(parallelMach,mesh);
156 
157  // finish up the edges
158 #ifndef ENABLE_UNIFORM
159  mesh.buildSubcells();
160 #endif
161  mesh.buildLocalElementIDs();
162 
163  // now that edges are built, sidsets can be added
164 #ifndef ENABLE_UNIFORM
165  addSideSets(mesh);
166 #endif
167 
168  // add nodesets
169  addNodeSets(mesh);
170 
171  // calls Stk_MeshFactory::rebalance
172  this->rebalance(mesh);
173 }
174 
177 {
179 
180  setMyParamList(paramList);
181 
182  x0_ = paramList->get<double>("X0");
183  y0_ = paramList->get<double>("Y0");
184 
185  xf_ = paramList->get<double>("Xf");
186  yf_ = paramList->get<double>("Yf");
187 
188  xBlocks_ = paramList->get<int>("X Blocks");
189  yBlocks_ = paramList->get<int>("Y Blocks");
190 
191  nXElems_ = paramList->get<int>("X Elements");
192  nYElems_ = paramList->get<int>("Y Elements");
193 
194  xProcs_ = paramList->get<int>("X Procs");
195  yProcs_ = paramList->get<int>("Y Procs");
196 
197  // read in periodic boundary conditions
198  parsePeriodicBCList(Teuchos::rcpFromRef(paramList->sublist("Periodic BCs")),periodicBCVec_);
199 }
200 
203 {
204  static RCP<Teuchos::ParameterList> defaultParams;
205 
206  // fill with default values
207  if(defaultParams == Teuchos::null) {
208  defaultParams = rcp(new Teuchos::ParameterList);
209 
210  defaultParams->set<double>("X0",0.0);
211  defaultParams->set<double>("Y0",0.0);
212 
213  defaultParams->set<double>("Xf",1.0);
214  defaultParams->set<double>("Yf",1.0);
215 
216  defaultParams->set<int>("X Blocks",1);
217  defaultParams->set<int>("Y Blocks",1);
218 
219  defaultParams->set<int>("X Procs",-1);
220  defaultParams->set<int>("Y Procs",1);
221 
222  defaultParams->set<int>("X Elements",5);
223  defaultParams->set<int>("Y Elements",5);
224 
225  Teuchos::ParameterList & bcs = defaultParams->sublist("Periodic BCs");
226  bcs.set<int>("Count",0); // no default periodic boundary conditions
227  }
228 
229  return defaultParams;
230 }
231 
233 {
234  // get valid parameters
236 
237  // set that parameter list
238  setParameterList(validParams);
239 }
240 
241 void SquareQuadMeshFactory::buildMetaData(stk::ParallelMachine /* parallelMach */, STK_Interface & mesh) const
242 {
243  typedef shards::Quadrilateral<4> QuadTopo;
244  const CellTopologyData * ctd = shards::getCellTopologyData<QuadTopo>();
245  const CellTopologyData * side_ctd = shards::CellTopology(ctd).getBaseCellTopologyData(1,0);
246 
247  // build meta data
248  //mesh.setDimension(2);
249  for(int bx=0;bx<xBlocks_;bx++) {
250  for(int by=0;by<yBlocks_;by++) {
251 
252  // add this element block
253  {
254  std::stringstream ebPostfix;
255  ebPostfix << "-" << bx << "_" << by;
256 
257  // add element blocks
258  mesh.addElementBlock("eblock"+ebPostfix.str(),ctd);
259  }
260 
261  }
262  }
263 
264  // add sidesets
265 #ifndef ENABLE_UNIFORM
266  mesh.addSideset("left",side_ctd);
267  mesh.addSideset("right",side_ctd);
268  mesh.addSideset("top",side_ctd);
269  mesh.addSideset("bottom",side_ctd);
270 
271  for(int bx=1;bx<xBlocks_;bx++) {
272  std::stringstream ss;
273  ss << "vertical_" << bx-1;
274  mesh.addSideset(ss.str(),side_ctd);
275  }
276  for(int by=1;by<yBlocks_;by++) {
277  std::stringstream ss;
278  ss << "horizontal_" << by-1;
279  mesh.addSideset(ss.str(),side_ctd);
280  }
281 #endif
282 
283  // add nodesets
284  mesh.addNodeset("lower_left");
285  mesh.addNodeset("origin");
286 }
287 
288 void SquareQuadMeshFactory::buildElements(stk::ParallelMachine parallelMach,STK_Interface & mesh) const
289 {
290  mesh.beginModification();
291  // build each block
292  for(int xBlock=0;xBlock<xBlocks_;xBlock++) {
293  for(int yBlock=0;yBlock<yBlocks_;yBlock++) {
294  buildBlock(parallelMach,xBlock,yBlock,mesh);
295  }
296  }
297  mesh.endModification();
298 }
299 
300 void SquareQuadMeshFactory::buildBlock(stk::ParallelMachine /* parallelMach */,int xBlock,int yBlock,STK_Interface & mesh) const
301 {
302  // grab this processors rank and machine size
303  std::pair<int,int> sizeAndStartX = determineXElemSizeAndStart(xBlock,xProcs_,machRank_);
304  std::pair<int,int> sizeAndStartY = determineYElemSizeAndStart(yBlock,yProcs_,machRank_);
305 
306  int myXElems_start = sizeAndStartX.first;
307  int myXElems_end = myXElems_start+sizeAndStartX.second;
308  int myYElems_start = sizeAndStartY.first;
309  int myYElems_end = myYElems_start+sizeAndStartY.second;
310  int totalXElems = nXElems_*xBlocks_;
311  int totalYElems = nYElems_*yBlocks_;
312 
313  double deltaX = (xf_-x0_)/double(totalXElems);
314  double deltaY = (yf_-y0_)/double(totalYElems);
315 
316  std::vector<double> coord(2,0.0);
317 
318  // build the nodes
319  for(int nx=myXElems_start;nx<myXElems_end+1;++nx) {
320  coord[0] = this->getMeshCoord(nx, deltaX, x0_);
321  for(int ny=myYElems_start;ny<myYElems_end+1;++ny) {
322  coord[1] = this->getMeshCoord(ny, deltaY, y0_);
323 
324  mesh.addNode(ny*(totalXElems+1)+nx+1,coord);
325  }
326  }
327 
328  std::stringstream blockName;
329  blockName << "eblock-" << xBlock << "_" << yBlock;
330  stk::mesh::Part * block = mesh.getElementBlockPart(blockName.str());
331 
332  // build the elements
333  for(int nx=myXElems_start;nx<myXElems_end;++nx) {
334  for(int ny=myYElems_start;ny<myYElems_end;++ny) {
335  stk::mesh::EntityId gid = totalXElems*ny+nx+1;
336  std::vector<stk::mesh::EntityId> nodes(4);
337  nodes[0] = nx+1+ny*(totalXElems+1);
338  nodes[1] = nodes[0]+1;
339  nodes[2] = nodes[1]+(totalXElems+1);
340  nodes[3] = nodes[2]-1;
341 
342  RCP<ElementDescriptor> ed = rcp(new ElementDescriptor(gid,nodes));
343  mesh.addElement(ed,block);
344  }
345  }
346 }
347 
348 std::pair<int,int> SquareQuadMeshFactory::determineXElemSizeAndStart(int xBlock,unsigned int size,unsigned int /* rank */) const
349 {
350  std::size_t xProcLoc = procTuple_[0];
351  unsigned int minElements = nXElems_/size;
352  unsigned int extra = nXElems_ - minElements*size;
353 
354  TEUCHOS_ASSERT(minElements>0);
355 
356  // first "extra" elements get an extra column of elements
357  // this determines the starting X index and number of elements
358  int nume=0, start=0;
359  if(xProcLoc<extra) {
360  nume = minElements+1;
361  start = xProcLoc*(minElements+1);
362  }
363  else {
364  nume = minElements;
365  start = extra*(minElements+1)+(xProcLoc-extra)*minElements;
366  }
367 
368  return std::make_pair(start+nXElems_*xBlock,nume);
369 }
370 
371 std::pair<int,int> SquareQuadMeshFactory::determineYElemSizeAndStart(int yBlock,unsigned int size,unsigned int /* rank */) const
372 {
373  std::size_t yProcLoc = procTuple_[1];
374  unsigned int minElements = nYElems_/size;
375  unsigned int extra = nYElems_ - minElements*size;
376 
377  TEUCHOS_ASSERT(minElements>0);
378 
379  // first "extra" elements get an extra column of elements
380  // this determines the starting X index and number of elements
381  int nume=0, start=0;
382  if(yProcLoc<extra) {
383  nume = minElements+1;
384  start = yProcLoc*(minElements+1);
385  }
386  else {
387  nume = minElements;
388  start = extra*(minElements+1)+(yProcLoc-extra)*minElements;
389  }
390 
391  return std::make_pair(start+nYElems_*yBlock,nume);
392 }
393 
395 {
396  mesh.beginModification();
397 
398  std::size_t totalXElems = nXElems_*xBlocks_;
399  std::size_t totalYElems = nYElems_*yBlocks_;
400 
401  // get all part vectors
402  stk::mesh::Part * left = mesh.getSideset("left");
403  stk::mesh::Part * right = mesh.getSideset("right");
404  stk::mesh::Part * top = mesh.getSideset("top");
405  stk::mesh::Part * bottom = mesh.getSideset("bottom");
406 
407  std::vector<stk::mesh::Part*> vertical;
408  std::vector<stk::mesh::Part*> horizontal;
409  for(int bx=1;bx<xBlocks_;bx++) {
410  std::stringstream ss;
411  ss << "vertical_" << bx-1;
412  vertical.push_back(mesh.getSideset(ss.str()));
413  }
414  for(int by=1;by<yBlocks_;by++) {
415  std::stringstream ss;
416  ss << "horizontal_" << by-1;
417  horizontal.push_back(mesh.getSideset(ss.str()));
418  }
419 
420  std::vector<stk::mesh::Entity> localElmts;
421  mesh.getMyElements(localElmts);
422 
423  // loop over elements adding edges to sidesets
424  std::vector<stk::mesh::Entity>::const_iterator itr;
425  for(itr=localElmts.begin();itr!=localElmts.end();++itr) {
426  stk::mesh::Entity element = (*itr);
427  stk::mesh::EntityId gid = mesh.elementGlobalId(element);
428 
429  std::size_t nx,ny;
430  ny = (gid-1) / totalXElems;
431  nx = gid-ny*totalXElems-1;
432 
433  // vertical boundaries
435 
436  if(nx+1==totalXElems) {
437  stk::mesh::Entity edge = mesh.findConnectivityById(element, stk::topology::EDGE_RANK, 1);
438 
439  // on the right
440  if(mesh.entityOwnerRank(edge)==machRank_)
441  mesh.addEntityToSideset(edge,right);
442  }
443 
444  if(nx==0) {
445  stk::mesh::Entity edge = mesh.findConnectivityById(element, stk::topology::EDGE_RANK, 3);
446 
447  // on the left
448  if(mesh.entityOwnerRank(edge)==machRank_)
449  mesh.addEntityToSideset(edge,left);
450  }
451 
452  if(nx+1!=totalXElems && ((nx+1) % nXElems_==0)) {
453  stk::mesh::Entity edge = mesh.findConnectivityById(element, stk::topology::EDGE_RANK, 1);
454 
455  // on the right
456  if(mesh.entityOwnerRank(edge)==machRank_) {
457  int index = (nx+1)/nXElems_-1;
458  mesh.addEntityToSideset(edge,vertical[index]);
459  }
460  }
461 
462  if(nx!=0 && (nx % nXElems_==0)) {
463  stk::mesh::Entity edge = mesh.findConnectivityById(element, stk::topology::EDGE_RANK, 3);
464 
465  // on the left
466  if(mesh.entityOwnerRank(edge)==machRank_) {
467  int index = nx/nXElems_-1;
468  mesh.addEntityToSideset(edge,vertical[index]);
469  }
470  }
471 
472  // horizontal boundaries
474 
475  if(ny==0) {
476  stk::mesh::Entity edge = mesh.findConnectivityById(element, stk::topology::EDGE_RANK, 0);
477 
478  // on the bottom
479  if(mesh.entityOwnerRank(edge)==machRank_)
480  mesh.addEntityToSideset(edge,bottom);
481  }
482 
483  if(ny+1==totalYElems) {
484  stk::mesh::Entity edge = mesh.findConnectivityById(element, stk::topology::EDGE_RANK, 2);
485 
486  // on the top
487  if(mesh.entityOwnerRank(edge)==machRank_)
488  mesh.addEntityToSideset(edge,top);
489  }
490 
491  if(ny!=0 && (ny % nYElems_==0)) {
492  stk::mesh::Entity edge = mesh.findConnectivityById(element, stk::topology::EDGE_RANK, 0);
493 
494  // on the bottom
495  if(mesh.entityOwnerRank(edge)==machRank_) {
496  int index = ny/nYElems_-1;
497  mesh.addEntityToSideset(edge,horizontal[index]);
498  }
499  }
500 
501  if(ny+1!=totalYElems && ((ny+1) % nYElems_==0)) {
502  stk::mesh::Entity edge = mesh.findConnectivityById(element, stk::topology::EDGE_RANK, 2);
503 
504  // on the top
505  if(mesh.entityOwnerRank(edge)==machRank_) {
506  int index = (ny+1)/nYElems_-1;
507  mesh.addEntityToSideset(edge,horizontal[index]);
508  }
509  }
510  }
511 
512  mesh.endModification();
513 }
514 
516 {
517  mesh.beginModification();
518 
519  // get all part vectors
520  stk::mesh::Part * lower_left = mesh.getNodeset("lower_left");
521  stk::mesh::Part * origin = mesh.getNodeset("origin");
522 
523  // std::vector<stk::mesh::Entity> localElmts;
524  // mesh.getMyElements(localElmts);
525 
527  if(machRank_==0)
528  {
529  // add zero node to lower_left node set
530  stk::mesh::Entity node = bulkData->get_entity(mesh.getNodeRank(),1);
531  mesh.addEntityToNodeset(node,lower_left);
532 
533  // add zero node to origin node set
534  mesh.addEntityToNodeset(node,origin);
535  }
536 
537  mesh.endModification();
538 }
539 
542 {
543  std::size_t i=0,j=0;
544 
545  j = procRank/xProcs_;
546  procRank = procRank % xProcs_;
547  i = procRank;
548 
549  return Teuchos::tuple(i,j);
550 }
551 
552 } // end panzer_stk
void addNodeset(const std::string &name)
unsigned entityOwnerRank(stk::mesh::Entity entity) const
virtual Teuchos::RCP< STK_Interface > buildUncommitedMesh(stk::ParallelMachine parallelMach) const
void addEntityToNodeset(stk::mesh::Entity entity, stk::mesh::Part *nodeset)
T & get(const std::string &name, T def_value)
stk::mesh::Part * getElementBlockPart(const std::string &name) const
get the block count
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
std::pair< int, int > determineXElemSizeAndStart(int xBlock, unsigned int size, unsigned int rank) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void addEntityToSideset(stk::mesh::Entity entity, stk::mesh::Part *sideset)
void buildElements(stk::ParallelMachine parallelMach, STK_Interface &mesh) const
stk::mesh::Part * getNodeset(const std::string &name) const
stk::mesh::Part * getSideset(const std::string &name) const
std::pair< int, int > determineYElemSizeAndStart(int yBlock, unsigned int size, unsigned int rank) const
void addElement(const Teuchos::RCP< ElementDescriptor > &ed, stk::mesh::Part *block)
Teuchos::RCP< STK_Interface > buildMesh(stk::ParallelMachine parallelMach) const
Build the mesh object.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void initialize(stk::ParallelMachine parallelMach, bool setupIO=true, const bool buildRefinementSupport=false)
SquareQuadMeshFactory(bool enableRebalance=false)
Constructor.
void rebalance(STK_Interface &mesh) const
Teuchos::RCP< stk::mesh::BulkData > getBulkData() const
stk::mesh::EntityId elementGlobalId(std::size_t lid) const
void setMyParamList(const RCP< ParameterList > &paramList)
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
void buildBlock(stk::ParallelMachine machRank, int xBlock, int yBlock, STK_Interface &mesh) const
Teuchos::Tuple< std::size_t, 2 > procRankToProcTuple(std::size_t procRank) const
what is the 2D tuple describe this processor distribution
void addNode(stk::mesh::EntityId gid, const std::vector< double > &coord)
void buildSubcells()
force the mesh to build subcells: edges and faces
bool isInitialized() const
Has initialize been called on this mesh object?
stk::mesh::Entity findConnectivityById(stk::mesh::Entity src, stk::mesh::EntityRank tgt_rank, unsigned rel_id) const
void addSideset(const std::string &name, const CellTopologyData *ctData)
double getMeshCoord(const int nx, const double deltaX, const double x0) const
void buildMetaData(stk::ParallelMachine parallelMach, STK_Interface &mesh) const
std::vector< Teuchos::RCP< const PeriodicBC_MatcherBase > > periodicBCVec_
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &paramList)
From ParameterListAcceptor.
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
void getMyElements(std::vector< stk::mesh::Entity > &elements) const
#define TEUCHOS_ASSERT(assertion_test)
stk::mesh::EntityRank getNodeRank() const
virtual void completeMeshConstruction(STK_Interface &mesh, stk::ParallelMachine parallelMach) const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
From ParameterListAcceptor.
void addElementBlock(const std::string &name, const CellTopologyData *ctData)
static void parsePeriodicBCList(const Teuchos::RCP< Teuchos::ParameterList > &pl, std::vector< Teuchos::RCP< const PeriodicBC_MatcherBase > > &periodicBC)