IFEM  90A354
SIMSemi3D.h
Go to the documentation of this file.
1 // $Id$
2 //==============================================================================
12 //==============================================================================
13 
14 #ifndef _SIM_SEMI3D_H
15 #define _SIM_SEMI3D_H
16 
17 #include "SIMadmin.h"
18 #include "SIMdependency.h"
19 #include "SIMconfigure.h"
20 #include "IFEM.h"
21 #include "Utilities.h"
22 #include "MatVec.h"
23 #include "Vec3.h"
24 #include "DataExporter.h"
25 #include "HDF5Writer.h"
26 #include "tinyxml2.h"
27 #include <fstream>
28 #include <memory>
29 
30 class TimeStep;
31 class VTF;
32 
34 extern std::vector<DataExporter*> plane_exporters;
36 extern std::vector< std::shared_ptr<std::ostream> > plane_log_files;
37 
38 
43 template<class PlaneSolver>
44 class SIMSemi3D : public SIMadmin, public SIMdependency
45 {
46 public:
47  typedef typename PlaneSolver::SetupProps SetupProps;
48 
50  enum { dimension = 2 };
51 
53  explicit SIMSemi3D(const SetupProps& props_) :
55  direction('Z'), props(props_)
56  {
57  SIMadmin::myHeading = "Plane-decoupled 3D simulation driver";
58  }
59 
61  virtual ~SIMSemi3D()
62  {
63  if (!m_planes.empty())
64  delete m_planes.front();
65 
66  for (size_t i = 1; i < m_planes.size(); i++)
67  {
68  // The other planes do not own the integrand, so clear the pointer to it
69  // to avoid that the SIMbase destructor tries to delete it again
70  m_planes[i]->clearProblem();
71  delete m_planes[i];
72  }
73  }
74 
77  {
78  bool ok = true;
79  for (size_t i = 0; i < m_planes.size() && ok; i++)
80  ok = m_planes[i]->advanceStep(tp);
81 
82  return ok;
83  }
84 
86  int getBDForder() const
87  {
88  return m_planes.empty() ? 0 : m_planes.front()->getBDForder();
89  }
90 
92  int getDumpInterval() const
93  {
94  return m_planes.empty() ? 1 : m_planes.front()->getDumpInterval();
95  }
96 
98  void printFinalNorms(const TimeStep&) {}
99 
101  bool preprocess(const std::vector<int>& = {}, bool = false) override
102  {
103  for (PlaneSolver* plane : m_planes)
104  if (!plane->preprocess())
105  return false;
106 
107  this->grabPlaneNodes();
108  return true;
109  }
110 
113  {
114  planeNodes.resize(this->getNoPlanes());
115  for (size_t i = 0; i <m_planes.size(); i++)
116  planeNodes[startCtx+i] = m_planes[i]->getNoNodes();
117 
118 #ifdef HAVE_MPI
119  std::vector<int> send(planeNodes);
120  MPI_Allreduce(&send[0], &planeNodes[0], planeNodes.size(),
121  MPI_INT, MPI_SUM, PETSC_COMM_WORLD);
122 #endif
123  }
124 
126  std::string getName() const override { return "Semi3D"; }
127 
129  void registerFields(const DataExporter& exporter)
130  {
131  std::string name = exporter.getName();
132  int plane = 1 + startCtx;
133  for (size_t i = 0; i < m_planes.size(); i++, plane++)
134  if (plane_exporters.size() <= i) {
135  DataExporter* exp = new DataExporter(true,exporter.getStride());
136  std::stringstream str;
137  str << "_plane" << plane;
138  HDF5Writer* hdf = new HDF5Writer(name+str.str(),
139  m_planes[i]->getProcessAdm(),false);
140  exp->registerWriter(hdf);
141  plane_exporters.push_back(exp);
142  m_planes[i]->registerFields(*exp);
143  }
144  else
145  m_planes[i]->registerFields(*plane_exporters[i]);
146  }
147 
149  bool init(const TimeStep& tp)
150  {
151  bool ok = true;
152  for (size_t i = 0; i < m_planes.size() && ok; i++)
153  ok = m_planes[i]->init(tp);
154 
155  return ok;
156  }
157 
159  bool saveModel(char*,int&,int&) { return true; }
160 
162  bool saveStep(const TimeStep& tp, int&)
163  {
164  for (size_t i = 0; i < plane_exporters.size(); i++)
165  plane_exporters[i]->dumpTimeLevel(&tp);
166 
167  // Note: VTF export is not supported for the Semi3D simulators.
168  // Instead this method is used for the HDF5 export.
169  return true;
170  }
171 
173  bool serialize(std::map<std::string,std::string>&) { return false; }
175  bool deSerialize(const std::map<std::string,std::string>&) { return false; }
176 
178  bool solveStep(TimeStep& tp)
179  {
180  bool ok = true;
181  for (size_t i = 0; i < m_planes.size() && ok; i++) {
182  m_planes[i]->getProcessAdm().cout <<"\n Plane = "<< startCtx+i+1 <<":";
183  ok = m_planes[i]->solveStep(tp);
184  }
185 
186  return ok;
187  }
188 
191  {
192  bool ok = true;
193  for (size_t i=0;i<m_planes.size();++i)
194  ok &= m_planes[i]->setInitialConditions();
195 
196  return ok;
197  }
198 
200  void initSystem()
201  {
202  for (size_t i=0;i<m_planes.size();++i)
203  m_planes[i]->initSystem();
204  }
205 
208  bool read(const char* fileName) override
209  {
210  if (!this->SIMadmin::read(fileName))
211  return false;
212 
213  // Setup our communicator
214 #ifdef HAVE_MPI
215  size_t loc_planes = planes/(nProc/procs_per_plane);
216  MPI_Comm comm;
217  MPI_Comm_split(PETSC_COMM_WORLD,
219  myPid%procs_per_plane, &comm);
220  startCtx = loc_planes*(myPid/procs_per_plane);
221 #else
222  size_t loc_planes = planes;
223 #endif
224 
225  for (size_t i=0;i<loc_planes;++i) {
226  m_planes.push_back(new PlaneSolver(props));
227 #ifdef HAVE_MPI
228  m_planes.back()->setCommunicator(&comm);
229 #endif
230  if (!log_files.empty()) {
231  int pid = 0;
232 #ifdef HAVE_MPI
233  MPI_Comm_rank(comm, &pid);
234 #endif
235  if (plane_log_files.size() < loc_planes) {
236  std::stringstream str;
237  str << log_files <<"_plane"<< startCtx+i+1 <<".log";
238  std::shared_ptr<std::ostream> file(new std::ofstream(str.str()));
239  plane_log_files.push_back(file);
240  }
241  m_planes[i]->getProcessAdm().cout.addExtraLog(plane_log_files[i],true);
242  m_planes[i]->getProcessAdm().cout.setPIDs(0, pid);
243  }
244  if (output_plane != -1 && output_plane != (int)(i+startCtx+1))
245  m_planes[i]->getProcessAdm().cout.setNull();
246  else
247  m_planes[i]->getProcessAdm().cout.setStream(std::cout);
248  }
249 
250  return true;
251  }
252 
253  using SIMadmin::parse;
256  bool parse(const tinyxml2::XMLElement* elem) override
257  {
258  if (!strcasecmp(elem->Value(),"postprocessing")) {
259  const tinyxml2::XMLElement* child = elem->FirstChildElement();
260  for (; child; child = child->NextSiblingElement())
261  opt.parseOutputTag(child);
262  }
263  if (strcasecmp(elem->Value(),"semi3d"))
264  return true;
265 
266  utl::getAttribute(elem, "nplanes", planes);
267 #ifdef HAVE_MPI
268  utl::getAttribute(elem, "procs_per_plane", procs_per_plane);
269  if (procs_per_plane > (size_t)nProc) procs_per_plane = nProc;
270 #endif
271  std::string dir("Z");
272  if (utl::getAttribute(elem, "direction", dir))
273  direction = toupper(dir[0]);
274 
275  utl::getAttribute(elem,"output_prefix", log_files);
276  utl::getAttribute(elem,"output_plane", output_plane);
277 
278  IFEM::cout <<"\tSemi3D: "<< direction
279  <<" "<< planes <<" planes, "<< procs_per_plane
280  <<" proces"<< (procs_per_plane > 1 ? "ses":"s") <<" per plane."
281  <<"\n\tSemi3D: Printing output from ";
282  if (output_plane == -1)
283  IFEM::cout <<"all planes to screen."<< std::endl;
284  else
285  IFEM::cout <<"plane "<< output_plane <<" to screen."<< std::endl;
286  if (!log_files.empty())
287  IFEM::cout <<"\tSemi3D: Logging to files with prefix "
288  << log_files <<"."<< std::endl;
289 
290  return true;
291  }
292 
301  template<class T>
302  void registerDependency(SIMSemi3D<T>* sim, const std::string& name,
303  short int nvc, const PatchVec& patches,
304  char diffBasis = 0, int component = 0)
305  {
306  for (size_t i=0;i<m_planes.size(); ++i)
307  if (diffBasis)
308  m_planes[i]->registerDependency(sim->getPlane(i), name, nvc,
309  sim->getPlane(i)->getFEModel(),
310  diffBasis, component);
311  else
312  m_planes[i]->registerDependency(sim->getPlane(i), name, nvc);
313  }
314 
316  size_t getNoSpaceDim() const override { return 2; }
318  size_t getNoPlanes() const { return planes; }
319 
321  PlaneSolver* getPlane(size_t i) { return m_planes[i]; }
323  const std::vector<PlaneSolver*>& getPlanes() const { return m_planes; }
324 
326  size_t getStartContext() const { return startCtx; }
327 
329  size_t getProcsPerPlane() const { return procs_per_plane; }
330 
332  int getPlaneNodes(int plane) const { return planeNodes[plane]; }
333 
335  char getDirection() const { return direction; }
336 
338  VTF* getVTF() { return NULL; }
340  void setVTF(VTF*) {}
341 
343  Vec3 getForce(int) const { return Vec3(); }
345  const PatchVec& getFEModel() { static PatchVec vec; return vec; }
346 
349  {
350  for (size_t i=0;i<m_planes.size();++i)
352  }
353 
355  bool updateALE()
356  {
357  bool ok = true;
358  for (size_t i = 0; i < m_planes.size() && ok; i++)
359  ok = m_planes[i]->updateALE();
360 
361  return ok;
362  }
363 
365  int getLocalNode(int) const { return -1; }
367  int getGlobalNode(int) const { return -1; }
368 
370  int getNoBasis() const { return m_planes.front()->getNoBasis(); }
371 
373  size_t getNoSolutions() const { return m_planes.front()->getNoSolutions(); }
374 
375 protected:
376  std::vector<PlaneSolver*> m_planes;
377 
378 private:
379  size_t startCtx;
380  size_t planes;
383  char direction;
384  std::string log_files;
385  std::vector<int> planeNodes;
387 };
388 
389 
391 template<class PlaneSolver>
392 struct SolverConfigurator< SIMSemi3D<PlaneSolver> > {
398  const typename PlaneSolver::SetupProps& props,
399  char* infile)
400  {
401  int retval = simulator.read(infile) ? 0 : 1;
402 
403  for (size_t i = 0; i < simulator.getPlanes().size() && retval == 0; i++) {
404  simulator.getPlane(i)->setContext(i+simulator.getStartContext()+1);
405  retval = ConfigureSIM(*simulator.getPlane(i), infile, props);
406  }
407  simulator.opt = simulator.getPlane(0)->opt;
408 
409  return retval;
410  }
411 };
412 
413 #endif
Administer and write data using DataWriters.
Output of model and results to HDF5 file.
Initialization of the IFEM library.
Global algebraic operations on index 1-based matrices and vectors.
std::vector< std::shared_ptr< std::ostream > > plane_log_files
Log files for the planes.
Definition: SIMSemi3D.C:19
std::vector< DataExporter * > plane_exporters
Data exporters for the planes.
Definition: SIMSemi3D.C:18
Administration base class for FEM simulators.
SIM solver configurator.
int ConfigureSIM(T &sim, char *infile, const typename T::SetupProps &props=typename T::SetupProps())
Configuration template.
Definition: SIMconfigure.h:38
Administration of simulators with dependencies to other simulators.
Various utility methods.
Representation of a point in 3D space with some basic operations.
Administer and write data using DataWriters.
Definition: DataExporter.h:38
std::string getName() const
Returns name from (first) data writer.
Definition: DataExporter.C:189
int getStride() const
Returns the data dump stride.
Definition: DataExporter.h:134
void registerWriter(DataWriter *writer)
Adds the data writer to the list of registered writers.
Definition: DataExporter.h:90
Write data to a HDF5 file.
Definition: HDF5Writer.h:30
static utl::LogStream cout
Combined standard out for parallel processes.
Definition: IFEM.h:62
Driver class for plane-decoupled 3D problems.
Definition: SIMSemi3D.h:45
std::string getName() const override
Returns the name of this simulator (for use in the HDF5 export).
Definition: SIMSemi3D.h:126
bool updateALE()
Updating the grid in an ALE solver.
Definition: SIMSemi3D.h:355
PlaneSolver::SetupProps SetupProps
Convenience type.
Definition: SIMSemi3D.h:47
bool parse(const tinyxml2::XMLElement *elem) override
Parses a data section from an XML element.
Definition: SIMSemi3D.h:256
void setVTF(VTF *)
Dummy method.
Definition: SIMSemi3D.h:340
std::vector< PlaneSolver * > m_planes
Planar solvers.
Definition: SIMSemi3D.h:376
VTF * getVTF()
Dummy method.
Definition: SIMSemi3D.h:338
int output_plane
Plane to print to screen for (-1 for all)
Definition: SIMSemi3D.h:382
bool saveStep(const TimeStep &tp, int &)
Dumps all registered fields for each plane.
Definition: SIMSemi3D.h:162
int getLocalNode(int) const
Dummy method.
Definition: SIMSemi3D.h:365
size_t getStartContext() const
Returns the context of the first plane on this process.
Definition: SIMSemi3D.h:326
void registerDependency(SIMSemi3D< T > *sim, const std::string &name, short int nvc, const PatchVec &patches, char diffBasis=0, int component=0)
Registers a dependency on a field from another SIM object.
Definition: SIMSemi3D.h:302
SIMSemi3D(const SetupProps &props_)
The constructor initializes the setup properties.
Definition: SIMSemi3D.h:53
SetupProps props
Setup properties to configure planar solvers.
Definition: SIMSemi3D.h:386
char getDirection() const
Returns the (unoriented) normal direction of the planes.
Definition: SIMSemi3D.h:335
bool read(const char *fileName) override
Reads model data from the specified input file.
Definition: SIMSemi3D.h:208
size_t getProcsPerPlane() const
Returns the number or processes participating in each planar solve.
Definition: SIMSemi3D.h:329
size_t procs_per_plane
Number of processes per plane.
Definition: SIMSemi3D.h:381
bool init(const TimeStep &tp)
Initializes for time-dependent simulation.
Definition: SIMSemi3D.h:149
size_t getNoSpaceDim() const override
Returns the spatial dimension of plane solvers.
Definition: SIMSemi3D.h:316
int getGlobalNode(int) const
Dummy method.
Definition: SIMSemi3D.h:367
size_t planes
Total number of planes.
Definition: SIMSemi3D.h:380
bool setInitialConditions()
Sets the initial conditions.
Definition: SIMSemi3D.h:190
size_t getNoSolutions() const
Returns the number of solution vectors.
Definition: SIMSemi3D.h:373
size_t startCtx
Context for first plane on this process.
Definition: SIMSemi3D.h:379
void printFinalNorms(const TimeStep &)
Dummy method.
Definition: SIMSemi3D.h:98
std::string log_files
Log file prefix for planes.
Definition: SIMSemi3D.h:384
void grabPlaneNodes()
Get FSI nodes for all planes.
Definition: SIMSemi3D.h:112
bool saveModel(char *, int &, int &)
Dummy method (VTF export is not supported).
Definition: SIMSemi3D.h:159
Vec3 getForce(int) const
Dummy method.
Definition: SIMSemi3D.h:343
void registerFields(const DataExporter &exporter)
Adds fields to a data exporter.
Definition: SIMSemi3D.h:129
bool advanceStep(TimeStep &tp)
Advances the time step one step forward.
Definition: SIMSemi3D.h:76
const std::vector< PlaneSolver * > & getPlanes() const
Returns a const reference to the plane solvers.
Definition: SIMSemi3D.h:323
void setupDependencies()
Setup inter-SIM dependencies.
Definition: SIMSemi3D.h:348
std::vector< int > planeNodes
FSI nodes for all planes.
Definition: SIMSemi3D.h:385
bool solveStep(TimeStep &tp)
Solves the nonlinear equations by Newton-Raphson iterations.
Definition: SIMSemi3D.h:178
int getDumpInterval() const
Returns the visualization dump interval.
Definition: SIMSemi3D.h:92
int getPlaneNodes(int plane) const
Returns the number of FSI nodes for a plane.
Definition: SIMSemi3D.h:332
int getNoBasis() const
Returns the number of bases in the model.
Definition: SIMSemi3D.h:370
virtual ~SIMSemi3D()
The destructor deletes the plane-wise sub-step solvers.
Definition: SIMSemi3D.h:61
PlaneSolver * getPlane(size_t i)
Returns a pointer to a given plane solver.
Definition: SIMSemi3D.h:321
bool serialize(std::map< std::string, std::string > &)
Dummy method, no serialization support.
Definition: SIMSemi3D.h:173
bool deSerialize(const std::map< std::string, std::string > &)
Dummy method, no deserialization support.
Definition: SIMSemi3D.h:175
const PatchVec & getFEModel()
Dummy method.
Definition: SIMSemi3D.h:345
int getBDForder() const
Returns the order of the BDF scheme.
Definition: SIMSemi3D.h:86
void initSystem()
Initialize the FEM system.
Definition: SIMSemi3D.h:200
char direction
(Unoriented) normal direction of plane
Definition: SIMSemi3D.h:383
bool preprocess(const std::vector< int > &={}, bool=false) override
Performs some pre-processing tasks on the FE model.
Definition: SIMSemi3D.h:101
size_t getNoPlanes() const
Returns the number of plane solvers.
Definition: SIMSemi3D.h:318
Administration base class for FEM simulators.
Definition: SIMadmin.h:32
std::string myHeading
Heading written before reading the input file.
Definition: SIMadmin.h:91
virtual bool read(const char *fileName)
Reads model data from the specified input file *fileName.
Definition: SIMadmin.C:68
int myPid
Processor ID in parallel simulations.
Definition: SIMadmin.h:89
int nProc
Number of processors in parallel simulations.
Definition: SIMadmin.h:90
SIMoptions & opt
Simulation control parameters.
Definition: SIMadmin.h:82
virtual bool parse(char *keyWord, std::istream &is)
Parses a data section from an input stream.
Definition: SIMadmin.C:113
Class administering inter-SIM field dependencies.
Definition: SIMdependency.h:30
std::vector< ASMbase * > PatchVec
Spline patch container.
Definition: SIMdependency.h:33
virtual void registerDependency(SIMdependency *sim, const std::string &name, short int nvc, const PatchVec &patches, char diffBasis=0, int component=1)
Registers a dependency on a field from another SIM object.
Definition: SIMdependency.C:21
bool parseOutputTag(const tinyxml2::XMLElement *elem)
Parses a subelement of the resultoutput XML-tag.
Definition: SIMoptions.C:156
Class for encapsulation of general time stepping parameters.
Definition: TimeStep.h:31
Class for output of FE model and results to VTF file.
Definition: VTF.h:58
Simple class for representing a point in 3D space.
Definition: Vec3.h:27
int getAttribute(const tinyxml2::XMLElement *xml, const char *att, bool &val)
Extracts a boolean attribute value from the specified XML-element.
Definition: Utilities.C:188
int setup(SIMSemi3D< PlaneSolver > &simulator, const typename PlaneSolver::SetupProps &props, char *infile)
Configure a SIMSemi3D.
Definition: SIMSemi3D.h:397
Struct for configuring a given simulator.
Definition: SIMconfigure.h:24