00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef SHELLMANAGERSPECIFIC_H
00014 #define SHELLMANAGERSPECIFIC_H
00015 #include <vector>
00016 #include <fstream>
00017 #include <string>
00018 #include <limits>
00019
00020 #include "mpi.h"
00021 #include "elc/LagrangianComm.h"
00022
00023 #include "shells/driverCC/ShellManagerBasic.h"
00024 #include "shells/parallel/ShellManagerParallel.h"
00025 #include "shells/utilities/BasicSensor.h"
00026 #include "shells/utilities/MakeUniqueName.h"
00027 #include "shells/utilities/PropertiesParser.h"
00028 #include "shells/driverCC/SVertexFunctors.h"
00029 #include "shells/driverCC/PrescribeVarFunctor.h"
00030 #include <shells/driverCC/StableTimeStep.h>
00031
00032 #include "ShellEnforceBCFunctor.h"
00033
00034 typedef shells::ShellManagerParallel<shells::ShellManagerBasic> SMPF;
00035
00036
00037 class ShellManagerSpecific : public SMPF {
00038 private:
00039 typedef utilities::BasicSensor<shells::SVertexDisplacement> BasicSensorSp;
00040
00041 public:
00042 ShellManagerSpecific(const std::string& controlFileName, MPI_Comm solidComm,
00043 int numFluidNodes, int firstFluidNode) :
00044 SMPF(controlFileName, solidComm), _timeStepReduction(1.), _subIterations(1),
00045 _sensoroutput(0), _panelheight(0.), _pressure(0.) {
00046
00047 #ifdef DEBUG_PRINT
00048 int myRank;
00049 std::ostringstream obuf;
00050 MPI_Comm_rank(solidComm, &myRank);
00051 obuf << "S" << myRank << ".log" << static_cast<char>(0);
00052 oflog.open(obuf.str().c_str());
00053 _olog = new std::ostream(oflog.rdbuf());
00054 #endif
00055
00056 computeMassPrepareAdvance();
00057
00058 #ifdef DEBUG_PRINT_ELC
00059 (*_olog << "*** LagrangianComm: " << numFluidNodes << " " << firstFluidNode ).flush();
00060 #endif
00061
00062 _elcLag = new elc::LagrangianComm<DIM, double>(MPI_COMM_WORLD, solidComm, numFluidNodes,
00063 firstFluidNode, elc::GlobalIdentifiers);
00064 #ifdef DEBUG_PRINT_ELC
00065 (*_olog << " created.\n").flush();
00066 #endif
00067
00068
00069 utilities::PropertiesParser *prop = new utilities::PropertiesParser;
00070 prop->registerPropertiesVar("timeStepReduction", _timeStepReduction);
00071 prop->registerPropertiesVar("SubIterations", _subIterations);
00072 prop->registerPropertiesVar("SensorOutput", _sensoroutput);
00073 prop->registerPropertiesVar("PanelHeight", _panelheight);
00074 prop->registerPropertiesVar("Pressure", _pressure);
00075 std::ifstream inputFile("./shellInput.dat");
00076 if (!inputFile.is_open()) assert(false);
00077 prop->readValues(inputFile);
00078 delete prop;
00079 inputFile.close();
00080
00081 #ifdef DEBUG_PRINT
00082 (*_olog << "*** ShellManagerSpecific created.\n").flush();
00083 #endif
00084
00085 if (_subIterations<=0)
00086 _subIterations=1;
00087 }
00088
00089
00090 ~ShellManagerSpecific() {
00091 if (_elcLag!=NULL) delete _elcLag;
00092 if (_olog!=NULL) delete _olog;
00093 if (_gnuplotFile!=NULL) {
00094 _gnuplotFile->close();
00095 delete _gnuplotFile;
00096 }
00097 }
00098
00099
00100 void sendBoundaryReceivePressure() {
00101 double *elCoordinates = NULL;
00102 double *elVelocities = NULL;
00103 int *elGlobalNodeIDs = NULL;
00104 int elNumNodes;
00105 int *elConnectivity = NULL;
00106 int elNumElements;
00107
00108 SMPF::decode(&elCoordinates, &elVelocities, &elGlobalNodeIDs,
00109 &elNumNodes, &elConnectivity, &elNumElements);
00110
00111
00112 _elPressures.resize(elNumElements);
00113 std::fill(_elPressures.begin(), _elPressures.end(), 0.0);
00114
00115 #ifdef DEBUG_PRINT_ELC
00116 ( *_olog << "*** ShellManagerSpecific::sendBoundaryReceivePressure" ).flush();
00117 #endif
00118
00119 _elcLag->sendMesh(elNumNodes, reinterpret_cast<void*>(elGlobalNodeIDs),
00120 reinterpret_cast<void*>(elCoordinates),
00121 reinterpret_cast<void*>(elVelocities),
00122 elNumElements, reinterpret_cast<void*>(elConnectivity));
00123 _elcLag->waitForMesh();
00124 _elcLag->receivePressure(elNumElements, reinterpret_cast<void*>(&(_elPressures[0])));
00125 _elcLag->waitForPressure();
00126
00127
00128 for (unsigned int n=0; n<_elPressures.size(); n++) {
00129 if (_elPressures[n] == std::numeric_limits<double>::max()) {
00130 _elPressures[n] = 0.0;
00131 }
00132
00133 if (_pressure != 0.)
00134 _elPressures[n] = _pressure;
00135 }
00136
00137 encodePressure(&(_elPressures[0]), _elPressures.size(), element);
00138
00139 #ifdef DEBUG_PRINT_ELC
00140 ( *_olog << " done.\n" ).flush();
00141 #endif
00142 }
00143
00144 virtual double stableTimeStep() {
00145 return _timeStepReduction*shells::computeStableTimeStep(SMPF::mShell(),
00146 SMPF::Thickness(),
00147 shells::MShell::active);
00148 }
00149
00150 virtual void advanceSp(double& t, double& dt){
00151 dt /= _subIterations;
00152 setTimeStep(dt);
00153
00154 #ifdef DEBUG_PRINT
00155 (*_olog << "*** advancing in time.\n").flush();
00156 #endif
00157
00158
00159 shells::ShellEnforceBCFunctor enforceBC;
00160 mShell()->iterateOverVertices(enforceBC);
00161 predict();
00162
00163 sendBoundaryReceivePressure();
00164 internalExternalForces();
00165 correct();
00166 incrementCurrentTimeAndStep();
00167
00168 for (int n=1; n<_subIterations; n++) {
00169 mShell()->iterateOverVertices(enforceBC);
00170 predict();
00171 internalExternalForces();
00172 correct();
00173 incrementCurrentTimeAndStep();
00174 }
00175
00176 dt = stableTimeStep()*_subIterations;
00177 t = getCurrentTime();
00178
00179
00180 if (_sensoroutput)
00181 std::for_each(_sensors.begin(), _sensors.end(),
00182 std::bind2nd(std::mem_fun(&BasicSensorSp::printData), t));
00183 }
00184
00185
00186 void addSensors(double xyz[3], bool restart=false) {
00187
00188 const int myRank = communicatorRank();
00189 std::string nameGnuplot = utilities::makeUniqueName(_sensors.size(), myRank, "./dispSensor-", "dat");
00190
00191 std::ofstream *gnuplotFile;
00192 if (restart) {
00193 gnuplotFile = new std::ofstream(nameGnuplot.c_str(), std::ofstream::app);
00194 } else {
00195 gnuplotFile = new std::ofstream(nameGnuplot.c_str());
00196 }
00197 BasicSensorSp *s = new BasicSensorSp(*gnuplotFile, ShellManagerBasic::mShell(), xyz);
00198
00199 _sensors.push_back(s);
00200 }
00201
00202
00203 void instrumentWithSensors(bool restart=false) {
00204 if (_sensoroutput<=0) return;
00205 double xyz[3] = { 0.05, 0.015, 0.};
00206 double dy = _panelheight/_sensoroutput;
00207 for (int n=0; n<_sensoroutput; n++) {
00208 xyz[1] += dy;
00209 addSensors(xyz, restart);
00210 }
00211 }
00212
00213
00214 void initialize(double& t, double& dt){
00215 sendBoundaryReceivePressure();
00216 dt = stableTimeStep()*_subIterations;
00217 t = getCurrentTime();
00218 if (_sensoroutput)
00219 instrumentWithSensors(false);
00220 }
00221
00222
00223 void output() {
00224 printDataParallel(true);
00225
00226 #ifdef DEBUG_PRINT
00227 ( *_olog << " Printing interface mesh and pressure.\n" ).flush();
00228 printIFaceMeshPressureParallel();
00229 #endif
00230 }
00231
00232
00233 int nSteps() {
00234 return getCurrentStepNum()/_subIterations;
00235 }
00236
00237
00238 void checkpointing() {
00239 checkPointingParallel();
00240 }
00241
00242 void restartSp(double& t, double& dt) {
00243 restartParallel();
00244 t = getCurrentTime();
00245 dt = stableTimeStep()*_subIterations;
00246
00247 shells::ShellEnforceBCFunctor enforceBC;
00248 mShell()->iterateOverVertices(enforceBC);
00249
00250 sendBoundaryReceivePressure();
00251
00252 if (_sensoroutput)
00253 instrumentWithSensors(true);
00254 }
00255
00256
00257
00258 private:
00259 ShellManagerSpecific(const ShellManagerSpecific &);
00260 const ShellManagerSpecific & operator=(const ShellManagerSpecific &);
00261
00262 private:
00263 elc::LagrangianComm<DIM, double> *_elcLag;
00264
00265 std::ostream *_olog;
00266 std::ofstream oflog;
00267
00268 std::ofstream *_gnuplotFile;
00269
00270 std::vector<double> _elPressures;
00271
00272 double _timeStepReduction;
00273
00274 int _subIterations;
00275
00276 int _sensoroutput;
00277
00278 double _panelheight;
00279
00280 double _pressure;
00281
00282 std::vector<BasicSensorSp *> _sensors;
00283 };
00284
00285 #endif