ElmerFoamFSI  2.0
ElmerFoamFSI is fluid-solid interaction simulation application built up from OpenFOAM CFD and Elmer CSM coupled through the IMPACT multiphysics software integration infrastructure.
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Macros Groups Pages
OFModuleDriver.C
Go to the documentation of this file.
1 #include "com.h"
11 #include "com_devel.hpp"
12 #include <iostream>
13 #include <cstring>
14 #include <cstdlib>
15 #include <sstream>
16 #include "primitive_utilities.H"
17 #include "SolverAgent.H"
18 #include "InterfaceLayer.H"
19 #include "OFModuleDriver.H"
20 
21 COM_EXTERN_MODULE(OpenFoamFSI);
22 
23 //using namespace std;
24 
25 int main(int argc, char *argv[]){
26  COM_init( &argc, &argv);
27 
28 
29  // flags for operation modes
30  // default mode of operation, runs the original OpenFOAM functionality
31  bool regression = true;
32  // prescribe a solid surface displacement and run the fluid solver only
33  bool prescribedDisplacement = false;
34 
35  std::string arg;
36  std::stringstream ss;
37 
38  // we read any driver specific flags passed
39  // the strings are then removed from argv and argc is decremented
40  // to preserve the input command line for OpenFoam
41  if (argc > 1) {
42  for (int i=1; i<argc; ++i) {
43  ss.clear();
44  ss.str("");
45  ss << argv[i];
46  if (ss.str() == "--driverRegression") {
47  regression = true;
48  } else if (ss.str() == "--driverPrescribedDisplacement") {
49  regression = false;
50  prescribedDisplacement = true;
51  } else {
52  Usage(argv[0]);
53  exit(2);
54  }
55  }
56  }
57 
58  COM_LOAD_MODULE_STATIC_DYNAMIC( OpenFoamFSI, "OFModule");
59 
61  int init_handle = COM_get_function_handle("OFModule.InitFoam");
62  if(init_handle <= 0) { // fail
63  std::cout << "OFModuleDriver:main: Could not get handle for init function." << std::endl;
64  exit(-1);
65  }
66 
67  // make a dummy argc/argv for OpenFOAM. No options passed from the command
68  // line will be used by the driver
69  int myArgc = 1;
70  char *myArgv[2];
71  myArgv[0] = argv[0];
72  myArgv[1] = NULL;
73  int verb=3;
74 
75  COM_call_function(init_handle, &myArgc, &myArgv, &verb);
76 
77  // get information about what was registered in this window
78  int numDataItems=0;
79  std::string output;
80  COM_get_dataitems("OFModule", &numDataItems, output);
81  std::istringstream Istr(output);
82  std::vector<std::string> dataItemNames;
83 
84  for (int i=0; i<numDataItems; ++i) {
85  std::string name;
86  Istr >> name;
87  dataItemNames.push_back(name);
88  std::cout << "OFModuleDriver:main: DataItem # " << i << ": " << name << std::endl;
89  }
90 
91  // list of panes in this window
92  int numPanes;
93  int* paneList;
94  COM_get_panes("OFModule", &numPanes, &paneList);
95  std::cout << "OFModuleDriver:main: Number of Panes " << numPanes << std::endl;
96  for (int i=0; i<numPanes; ++i)
97  std::cout << "OFModuleDriver:main: Pane ID # " << i+1 << "=" << paneList[i] << std::endl;
98 
99  // only one pane for serial runs
100  int pane = paneList[0];
101 
102  double* Coord;
103  COM_get_array("OFModule.nc", pane, &Coord);
104 
105  // check for expected number of nodes
106  int numNodes = 0;
107  COM_get_size("OFModule.nc", pane, &numNodes);
108 
109  // get connectivity tables for panes
110  int numConn;
111  std::string stringNames;
112  COM_get_connectivities("OFModule", pane, &numConn, stringNames);
113  std::istringstream ConnISS(stringNames);
114  std::vector<std::string> connNames;
115 
116  for (int i=0; i<numConn; ++i) {
117  std::string name;
118  ConnISS >> name;
119  connNames.push_back(name);
120  std::cout << "OFModuleDriver:main: Connectivity Table # " << i+1 << ": " << name << std::endl;
121  }
122 
123  // number of nodes per element
124  char getDataItemLoc;
125  COM_Type getDataItemType;
126  int numElementNodes;
127  std::string getDataItemUnits;
128  std::string fullConnName("OFModule."+connNames[0]);
129  COM_get_dataitem(fullConnName, &getDataItemLoc, &getDataItemType,
130  &numElementNodes, &getDataItemUnits);
131 
132  std::cout << "OFModuleDriver:main: getDataItemLoc " << getDataItemLoc << std::endl;
133  std::cout << "OFModuleDriver:main: getDataItemType " << getDataItemType << std::endl;
134  std::cout << "OFModuleDriver:main: numElementNodes " << numElementNodes << std::endl;
135  std::cout << "OFModuleDriver:main: getDataItemUnits " << getDataItemUnits << std::endl;
136 
137  int* Conn;
138  int numElem;
139  COM_get_array(fullConnName.c_str(), pane, &Conn);
140  COM_get_size(fullConnName, pane, &numElem);
141 
142  // put elements into a vector so we can build the solver agent
143  std::vector<unsigned int> connVector;
144  for (int i=0; i<numElem; ++i) {
145  for (int j=0; j<numElementNodes; ++j) {
146  connVector.push_back((Conn[i*numElementNodes+j]));
147  }
148  }
149 
150  // get non-mesh data items
151  int arrayLength;
152  std::string name("OFModule.time");
153  COM_get_dataitem(name, &getDataItemLoc, &getDataItemType,
154  &arrayLength, &getDataItemUnits);
155  double* time;
156  COM_get_array(name.c_str(), pane, &time);
157 
158  name = "OFModule.endTime";
159  COM_get_dataitem(name, &getDataItemLoc, &getDataItemType,
160  &arrayLength, &getDataItemUnits);
161  double* endTime;
162  COM_get_array(name.c_str(), pane, &endTime);
163 
164 
165  // make a solverAgent to store our data
166  SolverUtils::FEM::SolverAgent myAgent;
167 
169 
170  // set up solution meta data
171  myAgent.Solution().Meta().AddField("time", 's', 1, 8, "s");
172  myAgent.Solution().Meta().AddField("endTime", 's', 1, 8, "s");
173  //myAgent.Solution().Meta().AddField("initStatus", 's', 1, 4, "");
174  //myAgent.Solution().Meta().AddField("runStatus", 's', 1, 4, "");
175  //myAgent.Solution().Meta().AddField("dt", 's', 1, 8, "s");
176  //myAgent.Solution().Meta().AddField("displacement", 'n', 3, 8, "m");
177  //myAgent.Solution().Meta().AddField("traction", 'c', 1, 8, "N");
178 
179  myAgent.Mesh().nc.init(numNodes, Coord);
180  // this assumes that our elements are quads...we can generalize this
181  myAgent.Mesh().con.AddElements(numElem, numElementNodes, connVector);
182 
183  // get data registered on surface mesh
184  name = "OFModule.pressure";
185  COM_get_dataitem(name, &getDataItemLoc, &getDataItemType,
186  &arrayLength, &getDataItemUnits);
187 
188  std::cout << "OFModuleDriver:main: Pressure Get DataItem" << std::endl;
189  std::cout << "OFModuleDriver:main: getDataItemLoc: " << getDataItemLoc << std::endl;
190  std::cout << "OFModuleDriver:main: getDataItemType: " << getDataItemType << std::endl;
191  std::cout << "OFModuleDriver:main: arrayLength: " << arrayLength << std::endl;
192  std::cout << "OFModuleDriver:main: getDataItemUnits: " << getDataItemUnits << std::endl;
193 
194  char myDataItemLoc;
195  // translate element (e) to cell (c)
196  if (getDataItemLoc == 'e' || getDataItemLoc == 'E') {
197  myDataItemLoc = 'c';
198  } else {
199  std::cout << "OFModuleDriver:main: Unknown Data Item Location" << std::endl;
200  exit(1);
201  }
202 
203  int myDataItemType;
204  if (getDataItemType == COM_DOUBLE) {
205  myDataItemType = 8;
206  } else {
207  std::cout << "OFModuleDriver:main: Unknown Data Item Type" << std::endl;
208  exit(1);
209  }
210 
211  myAgent.Solution().Meta().AddField("surfacePressure", myDataItemLoc, arrayLength,
212  myDataItemType, getDataItemUnits);
213  double* surfacePressure;
214  COM_get_array(name.c_str(), pane, &surfacePressure);
215 
216  name = "OFModule.traction";
217  COM_get_dataitem(name, &getDataItemLoc, &getDataItemType,
218  &arrayLength, &getDataItemUnits);
219 
220  std::cout << "OFModuleDriver:main: Traction Get DataItem" << std::endl;
221  std::cout << "OFModuleDriver:main: getDataItemLoc: " << getDataItemLoc << std::endl;
222  std::cout << "OFModuleDriver:main: getDataItemType: " << getDataItemType << std::endl;
223  std::cout << "OFModuleDriver:main: arrayLength: " << arrayLength << std::endl;
224  std::cout << "OFModuleDriver:main: getDataItemUnits: " << getDataItemUnits << std::endl;
225 
226  // translate element (e) to cell (c)
227  if (getDataItemLoc == 'e' || getDataItemLoc == 'E') {
228  myDataItemLoc = 'c';
229  } else {
230  std::cout << "OFModuleDriver:main: Unknown Data Item Location" << std::endl;
231  exit(1);
232  }
233 
234  if (getDataItemType == COM_DOUBLE) {
235  myDataItemType = 8;
236  } else {
237  std::cout << "OFModuleDriver:main: Unknown Data Item Type" << std::endl;
238  exit(1);
239  }
240 
241  myAgent.Solution().Meta().AddField("surfaceTraction", myDataItemLoc, arrayLength,
242  myDataItemType, getDataItemUnits);
243  double* surfaceTraction;
244  COM_get_array(name.c_str(), pane, &surfaceTraction);
245 
246  name = "OFModule.solidDisplacement";
247  COM_get_dataitem(name, &getDataItemLoc, &getDataItemType,
248  &arrayLength, &getDataItemUnits);
249 
250  std::cout << "OFModuleDriver:main: Solid Displacement Get DataItem" << std::endl;
251  std::cout << "OFModuleDriver:main: getDataItemLoc: " << getDataItemLoc << std::endl;
252  std::cout << "OFModuleDriver:main: getDataItemType: " << getDataItemType << std::endl;
253  std::cout << "OFModuleDriver:main: arrayLength: " << arrayLength << std::endl;
254  std::cout << "OFModuleDriver:main: getDataItemUnits: " << getDataItemUnits << std::endl;
255 
256  // translate element (e) to cell (c)
257  if (getDataItemLoc == 'e' || getDataItemLoc == 'E') {
258  myDataItemLoc = 'c';
259  } else if (getDataItemLoc == 'n' || getDataItemLoc == 'N') {
260  myDataItemLoc = 'n';
261  } else {
262  std::cout << "OFModuleDriver:main: Unknown Data Item Location" << std::endl;
263  exit(1);
264  }
265 
266  if (getDataItemType == COM_DOUBLE) {
267  myDataItemType = 8;
268  } else {
269  std::cout << "OFModuleDriver:main: Unknown Data Item Type" << std::endl;
270  exit(1);
271  }
272 
273  myAgent.Solution().Meta().AddField("solidDisplacement", myDataItemLoc, arrayLength,
274  myDataItemType, getDataItemUnits);
275  double* solidDisplacement;
276  COM_get_array("OFModule.solidDisplacement", pane, &solidDisplacement);
277 
278  // create buffers for the actual data
279  myAgent.CreateSoln();
280 
281  unsigned int nnodes = myAgent.Mesh().nc.NNodes();
282  unsigned int nelem = myAgent.Mesh().con.Nelem();
283 
284  // reset the buffers to be our own local buffers
285  myAgent.Solution().SetFieldBuffer("time", time);
286  myAgent.Solution().SetFieldBuffer("endTime", endTime);
287  myAgent.Solution().SetFieldBuffer("surfacePressure", surfacePressure);
288  myAgent.Solution().SetFieldBuffer("surfaceTraction", surfaceTraction);
289  myAgent.Solution().SetFieldBuffer("solidDisplacement", solidDisplacement);
290 
292  int run_handle = COM_get_function_handle("OFModule.RunFoam");
293  if(run_handle <= 0) { // fail
294  std::cout << "OFModuleDriver:main: Could not get handle for run function." << std::endl;
295  exit(-1);
296  }
297 
298  int step_handle;
300  if (regression) {
301  step_handle = COM_get_function_handle("OFModule.StepFoam");
302  std::cout << "OFModuleDriver:main: StepFoam will be running shortly." << std::endl;
303  if(step_handle <= 0) { // fail
304  std::cout << "OFModuleDriver:main: Could not get handle for step function." << std::endl;
305  exit(-1);
306  }
307  } else if (prescribedDisplacement) {
308  step_handle = COM_get_function_handle("OFModule.StepFluid");
309  std::cout << "OFModuleDriver:main: StepFluid will be running shortly." << std::endl;
310  if(step_handle <= 0) { // fail
311  std::cout << "OFModuleDriver:main: Could not get handle for step fluid alone function." << std::endl;
312  exit(-1);
313  }
314  }
315 
317  std::ofstream Ouf;
318  ss.clear();
319  ss.str("");
320  ss << time[0];
321  std::string filename;
322  filename = "fsi" + ss.str() +".vtk";
323  Ouf.open(filename.c_str());
324  if(!Ouf){
325  std::cerr << "OFModuleDriver:main: OFModuleDriver::DumpSolution:Error: Could not open output file, "
326  << filename << "." << std::endl;
327  return -1;
328  }
329  std::cout << "OFModuleDriver:main: WriteVTKToStream time " << time[0] << std::endl;
330  SolverUtils::WriteVTKToStream("OFModule", myAgent, Ouf);
331  Ouf.close();
332 
333  std::cout << "OFModuleDriver:main: In Driver:" << " time=" << time[0] << " endTime=" << endTime[0] << std::endl;
334  while(time[0] <= endTime[0]) {
335  //COM_call_function(run_handle);
336  // step solution
337  if (prescribedDisplacement) {
338  double xmax = .6;
339  double xmin = .26;
340  double alpha = 3.141592/(2.0*(xmax-xmin));
341  double beta = 2*3.141592/endTime[0];
342  for(int i = 0;i < numNodes;i++){
343  double xpos = Coord[i*3] - xmin;
344  if(xpos > 0){
345  xpos *= alpha;
346  solidDisplacement[i*3] = solidDisplacement[i*3+2] = 0.0;
347  solidDisplacement[i*3+1] = 0.001*std::sin(xpos)*std::sin(beta*time[0]);
348  }
349  }
350  }
351  COM_call_function(step_handle);
353  std::ofstream Ouf;
354  ss.clear();
355  ss.str("");
356  ss << time[0];
357  std::string filename;
358  filename = "fsi" + ss.str() +".vtk";
359  Ouf.open(filename.c_str());
360  if(!Ouf){
361  std::cerr << "OFModuleDriver::DumpSolution:Error: Could not open output file, "
362  << filename << "." << std::endl;
363  return -1;
364  }
365  std::cout << "OFModuleDriver:main: WriteVTKToStream time " << time[0] << std::endl;
366  SolverUtils::WriteVTKToStream("OFModule", myAgent, Ouf);
367  Ouf.close();
368  }
369 
370  COM_UNLOAD_MODULE_STATIC_DYNAMIC(OpenFoamFSI, "OFModule");
371 
372  COM_finalize();
373  return(0);
374 }
375 
376 void Usage(char *exec) {
377  std::cout << "Usage: " << std::endl;
378  std::cout << exec << "<flags>" << std::endl
379  << "OFModuleDriver:Usage: Where flags is either --driverRegression or --driverPrescribedDisplacement" << std::endl
380  << "--driver Regresion runs a standard openFoam simulation" << std::endl
381  << "--driverPrescribedMotion runs openFoam with a fluid only solver and applies"
382  << "a prescribed displacement to the solid/fluid boundary" << std::endl;
383 }
COM_EXTERN_MODULE(OpenFoamFSI)
#define main
Definition: icoFoamModule.C:2
void Usage(char *exec)