LifeV
MultiscaleCoupling.cpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 
27 /*!
28  * @file
29  * @brief File containing the Multiscale Physical Coupling
30  *
31  * @date 02-09-2009
32  * @author Cristiano Malossi <cristiano.malossi@epfl.ch>
33  *
34  * @maintainer Cristiano Malossi <cristiano.malossi@epfl.ch>
35  */
36 
37 #include <lifev/multiscale/couplings/MultiscaleCoupling.hpp>
38 
39 namespace LifeV
40 {
41 namespace Multiscale
42 {
43 
45 
46 // ===================================================
47 // Constructors & Destructor
48 // ===================================================
50  M_ID (),
51  M_type (),
52  M_models (),
53  M_couplingName (),
54  M_boundaryIDs (),
55  M_globalData (),
63  M_perturbedCoupling ( false ),
64  M_comm ()
65 {
66 
67 #ifdef HAVE_LIFEV_DEBUG
68  debugStream ( 8200 ) << "MultiscaleCoupling::MultiscaleCoupling() \n";
69 #endif
70 
71 }
72 
73 // ===================================================
74 // Multiscale PhysicalCoupling Virtual Methods
75 // ===================================================
76 void
77 MultiscaleCoupling::setupData ( const std::string& fileName )
78 {
79 
80 #ifdef HAVE_LIFEV_DEBUG
81  debugStream ( 8200 ) << "MultiscaleCoupling::setupData( fileName ) \n";
82 #endif
83 
84  GetPot dataFile ( fileName );
85 
86  // Read Multiscale parameters
87  M_couplingName = dataFile ( "Multiscale/couplingName", "couplingName" );
88 
89  M_timeInterpolationOrder = dataFile ( "Multiscale/timeInterpolationOrder", 0 );
90  M_flowRateInterfaces = dataFile ( "Multiscale/flowRateInterfaces", 0 );
91 
92  // If flowRateInterfaces is negative all the interfaces get a flow rate
93  if ( M_flowRateInterfaces < 0 )
94  {
96  }
97 
98  // Set the size of the local coupling variables
99  if ( myModelsNumber() > 0 )
100  {
101  M_localCouplingVariables.reserve ( M_timeInterpolationOrder + 1 );
102  }
103 
104  // Set the number of coupling variables (default is 0)
105  if ( myModelsNumber() > 0 )
106  {
108  }
109 
110  // Create local vectors
112 }
113 
114 // ===================================================
115 // Methods
116 // ===================================================
117 bool
118 MultiscaleCoupling::isModelLeaderProcess ( const UInt& localModelID ) const
119 {
120  return M_models[localModelID]->communicator()->MyPID() == 0 ? true : false;
121 }
122 
123 void
125 {
126 
127 #ifdef HAVE_LIFEV_DEBUG
128  debugStream ( 8200 ) << "MultiscaleCoupling::createCouplingMap( couplingMap ) \n";
129 #endif
130 
131  M_couplingVariablesOffset = couplingMap.map ( Unique )->NumGlobalElements();
132 
133  couplingMap += localCouplingVariables ( 0 ).map();
134 }
135 
136 void
138 {
139 
140 #ifdef HAVE_LIFEV_DEBUG
141  debugStream ( 8200 ) << "MultiscaleCoupling::extrapolateCouplingVariables() \n";
142 #endif
143 
144  if ( myModelsNumber() > 0 )
145  {
146  // Extrapolate the coupling variables at the next time
147  multiscaleVector_Type extrapolatedCouplingVariables ( localCouplingVariables ( 0 ) );
148  interpolateCouplingVariables ( M_globalData->dataTime()->nextTime(), extrapolatedCouplingVariables );
149 
150  // If we have not yet enough samples for interpolation, we add a new one
151  UInt couplingVariablesSize ( M_localCouplingVariables.size() );
152  if ( couplingVariablesSize <= M_timeInterpolationOrder )
153  {
154  ++couplingVariablesSize;
155  M_localCouplingVariables.push_back ( multiscaleVectorPtr_Type ( new VectorEpetra ( localCouplingVariables ( 0 ) ) ) );
156  }
157 
158  // Updating database
159  for ( UInt i (1) ; i < couplingVariablesSize ; ++i )
160  {
161  localCouplingVariables ( couplingVariablesSize - i ) = localCouplingVariables ( couplingVariablesSize - i - 1 );
162  }
163 
164  localCouplingVariables ( 0 ) = extrapolatedCouplingVariables;
165 
166 #ifdef HAVE_LIFEV_DEBUG
167  for ( UInt i ( 0 ); i < M_couplingVariablesNumber; ++i )
168  {
169  debugStream ( 8200 ) << "C(" << M_couplingVariablesOffset + i << ") = " << ( localCouplingVariables ( 0 ) ) [i] << "\n";
170  }
171 #endif
172  }
173 }
174 
175 void
176 MultiscaleCoupling::interpolateCouplingVariables ( const Real& t, multiscaleVector_Type& interpolatedCouplingVariables ) const
177 {
178  // Coupling variables size
179  UInt couplingVariablesSize ( M_localCouplingVariables.size() );
180 
181  // Time container for interpolation
182  timeContainer_Type timeContainer ( couplingVariablesSize, 0 );
183  for ( UInt i (0) ; i < couplingVariablesSize ; ++i )
184  {
185  timeContainer[i] = M_globalData->dataTime()->time() - i * M_globalData->dataTime()->timeStep();
186  }
187 
188  // Lagrange interpolation
189  interpolatedCouplingVariables *= 0;
190  Real base (1);
191 
192  for ( UInt i (0) ; i < M_localCouplingVariables.size() ; ++i )
193  {
194  base = 1;
195  for ( UInt j (0) ; j < M_localCouplingVariables.size() ; ++j )
196  if ( j != i )
197  {
198  base *= (t - timeContainer[j]) / (timeContainer[i] - timeContainer[j]);
199  }
200 
201  interpolatedCouplingVariables += base * localCouplingVariables ( i );
202  }
203 }
204 
205 void
207 {
208 
209 #ifdef HAVE_LIFEV_DEBUG
210  debugStream ( 8200 ) << "MultiscaleCoupling::exportJacobian( jacobian ) \n";
211 #endif
212 
213  if ( myModelsNumber() > 0 )
214  {
215  // Definitions
216  bool solveLinearSystem; // Flag to avoid multiple solution of the same linear system
217  multiscaleModelsContainer_Type perturbedModelsList; // List of perturbed model
218 
219  // Insert constant values in the jacobian (due to this coupling condition)
221 
222  // Set as perturbed
224 
225  // Loop on all the local coupling variables that should be perturbed
226  for ( UInt column (M_couplingVariablesOffset) ; M_perturbedCoupling < static_cast< Int > ( M_couplingVariablesNumber ); ++M_perturbedCoupling, ++column )
227  {
228  // Build the list of models affected by the perturbation of the variable associated with this column
229  perturbedModelsList.clear();
231 
232  // Loop on all the models, that are influenced by the perturbation of the coupling variable
233  for ( multiscaleModelsContainerIterator_Type j = perturbedModelsList.begin() ; j < perturbedModelsList.end() ; ++j )
234  {
235  solveLinearSystem = true;
236 
237  // Loop on all the couplings (boundary flags) that connect the j-model
238  for ( UInt k (0) ; k < ( *j )->couplingsNumber() ; ++k )
239  {
240  ( *j )->coupling ( k )->insertJacobianDeltaCoefficients ( jacobian, column, ( *j )->ID(), solveLinearSystem );
241  }
242  }
243  }
244 
245  // Set as unperturbed
246  M_perturbedCoupling = -1;
247  }
248 }
249 
250 void
252 {
253 
254 #ifdef HAVE_LIFEV_DEBUG
255  debugStream ( 8200 ) << "MultiscaleCoupling::saveSolution() \n";
256 #endif
257 
258  if ( myModelsNumber() > 0 )
259  {
260  for ( UInt i ( 0 ); i < modelsNumber(); ++i )
261  if ( myModel ( i ) )
262  {
263  Real flowRate ( multiscaleDynamicCast< MultiscaleInterface > ( M_models[i] )->boundaryFlowRate ( M_boundaryIDs[i] ) );
264  Real stress ( multiscaleDynamicCast< MultiscaleInterface > ( M_models[i] )->boundaryMeanNormalStress ( M_boundaryIDs[i] ) );
265  Real totalStress ( multiscaleDynamicCast< MultiscaleInterface > ( M_models[i] )->boundaryMeanTotalNormalStress ( M_boundaryIDs[i] ) );
266  Real area ( multiscaleDynamicCast< MultiscaleInterface > ( M_models[i] )->boundaryArea ( M_boundaryIDs[i] ) );
267 
268  if ( isModelLeaderProcess ( i ) )
269  {
270  std::ofstream output;
271  output << std::scientific << std::setprecision ( 15 );
272 
273  std::string filename = multiscaleProblemFolder + multiscaleProblemPrefix + "_Coupling_" + number2string ( M_ID )
274  + "_Flag_" + number2string ( i )
275  + "_" + number2string ( multiscaleProblemStep ) + ".mfile";
276 
277  if ( M_globalData->dataTime()->timeStepNumber() == 0 || ( multiscaleProblemStep > 0 &&
278  M_globalData->dataTime()->round ( M_globalData->dataTime()->time() - ( multiscaleSaveEachNTimeSteps - 1 ) * M_globalData->dataTime()->timeStep() ) == M_globalData->dataTime()->round ( M_globalData->dataTime()->initialTime() ) ) )
279  {
280  output.open ( filename.c_str(), std::ios::trunc );
281  output << "% Coupling Type: " << enum2String ( M_type, multiscaleCouplingsMap ) << std::endl;
282  output << "% Coupling Name: " << M_couplingName << std::endl;
283  output << "% Model: " << number2string ( M_models[i]->ID() ) << std::endl;
284  output << "% Boundary Flag: " << number2string ( M_models[i]->boundaryFlag ( M_boundaryIDs[i] ) ) << std::endl << std::endl;
285  output << "% TIME FLOW RATE STRESS TOTAL STRESS AREA" << std::endl;
286  }
287  else
288  {
289  output.open ( filename.c_str(), std::ios::app );
290  }
291  output << " " << M_globalData->dataTime()->time() << " " << flowRate << " " << stress << " " << totalStress << " " << area << std::endl;
292  output.close();
293  }
294  }
295  }
296 }
297 
298 void
300 {
301  if ( myModelsNumber() > 0 )
302  {
303  std::cout << "Coupling id = " << M_ID << std::endl
304  << "Coupling name = " << M_couplingName << std::endl
305  << "Coupling type = " << enum2String ( M_type, multiscaleCouplingsMap ) << std::endl << std::endl;
306 
307  std::cout << "Interpolation order = " << M_timeInterpolationOrder << std::endl
308  << "Flow interfaces = " << M_flowRateInterfaces << std::endl << std::endl;
309 
310  std::cout << "Models ID(s) = ";
311  for ( UInt i ( 0 ); i < modelsNumber(); ++i )
312  if ( myModel ( i ) )
313  {
314  std::cout << M_models[i]->ID() << " ";
315  }
316  std::cout << std::endl;
317  std::cout << "Models type(s) = ";
318  for ( UInt i ( 0 ); i < modelsNumber(); ++i )
319  if ( myModel ( i ) )
320  {
321  std::cout << enum2String ( M_models[i]->type(), multiscaleModelsMap ) << " ";
322  }
323  std::cout << std::endl;
324  std::cout << "Flags list = ";
325  for ( UInt i ( 0 ); i < modelsNumber(); ++i )
326  if ( myModel ( i ) )
327  {
328  std::cout << M_boundaryIDs[i] << " ";
329  }
330  std::cout << std::endl << std::endl;
331  }
332 }
333 
334 void
336 {
337  if ( myModel ( 0 ) )
338  if ( isModelLeaderProcess ( 0 ) )
339  {
340  for ( UInt i ( 0 ); i < M_couplingVariablesNumber; ++i )
341  {
342  std::cout << "R(" << M_couplingVariablesOffset + i << ") = " << ( *M_localCouplingResiduals ) [i] << std::endl;
343  }
344  }
345 }
346 
347 void
349 {
350  if ( myModel ( 0 ) )
351  if ( isModelLeaderProcess ( 0 ) )
352  {
353  for ( UInt i ( 0 ); i < M_couplingVariablesNumber; ++i )
354  {
355  std::cout << "C(" << M_couplingVariablesOffset + i << ") = " << localCouplingVariables ( 0 ) [i] << std::endl;
356  }
357  }
358 }
359 
360 // ===================================================
361 // Get Methods
362 // ===================================================
363 UInt
365 {
366  if ( myModelsNumber() > 0 )
367  for ( UInt localID ( 0 ); localID < modelsNumber(); ++localID )
368  if ( myModel ( localID ) )
369  if ( M_models[localID]->ID() == ID )
370  {
371  return localID;
372  }
373 
374  std::cout << " !!! WARNING: modelGlobalToLocalID was not able to find the model ID !!! " << std::endl;
375  return 0;
376 }
377 
378 // ===================================================
379 // Protected Methods
380 // ===================================================
381 void
383 {
384  // Build a repeated list of GlobalElements
385  std::vector<Int> myGlobalElements ( M_couplingVariablesNumber );
386  for ( UInt i = 0 ; i < myGlobalElements.size() ; ++i )
387  {
388  myGlobalElements[i] = i;
389  }
390 
391  // Build a repeated map for the couplings
392  MapEpetra map ( -1, static_cast< Int > ( myGlobalElements.size() ), &myGlobalElements[0], M_comm );
393 
394  // Create local repeated vectors
395  M_localCouplingVariables.push_back ( multiscaleVectorPtr_Type ( new VectorEpetra ( map, Repeated ) ) );
396  M_localCouplingResiduals.reset ( new VectorEpetra ( map, Repeated ) );
397 }
398 
399 void
401 {
402  // Reset coupling variable history
403  for ( UInt i ( 0 ) ; i < M_localCouplingVariables.size() ; ++i )
404  {
405  localCouplingVariables ( i ) = 0;
406  }
407 }
408 
409 void
410 MultiscaleCoupling::importCouplingVector ( multiscaleVector_Type& repeatedLocalVector, const multiscaleVector_Type& uniqueGlobalVector, const combineMode_Type& combineMode )
411 {
412  multiscaleVector_Type uniqueLocalVector ( repeatedLocalVector.mapPtr(), Unique, combineMode );
413  uniqueLocalVector.subset ( uniqueGlobalVector, M_couplingVariablesOffset );
414 
415  repeatedLocalVector = uniqueLocalVector;
416 }
417 
418 void
419 MultiscaleCoupling::exportCouplingVector ( multiscaleVector_Type& uniqueGlobalVector, const multiscaleVector_Type& repeatedLocalVector, const combineMode_Type& combineMode )
420 {
421  multiscaleVector_Type localVectorUnique ( repeatedLocalVector, Unique, combineMode );
422  uniqueGlobalVector.replace ( localVectorUnique, M_couplingVariablesOffset );
423 }
424 
425 void
427 {
428  multiscaleErrorCheck ( ModelType, "Invalid model type [" + enum2String ( model->type(), multiscaleModelsMap ) +
429  "] for coupling type [" + enum2String ( M_type, multiscaleCouplingsMap ) + "]\n", model->communicator()->MyPID() == 0 );
430 }
431 
432 } // Namespace Multiscale
433 } // Namespace LifeV
UInt modelGlobalToLocalID(const UInt &ID) const
Get the model local ID through global ID.
void switchErrorMessage(const multiscaleModelPtr_Type &model)
Display and error message for the specific model.
UInt myModelsNumber() const
Determine the number of models owned by this coupling.
VectorEpetra & subset(const VectorEpetra &vector, const UInt offset=0)
Set the current vector to a subset of the given vector with an offset.
void showMeCouplingVariables() const
Display the local coupling variables.
void interpolateCouplingVariables(const Real &t, multiscaleVector_Type &interpolatedCouplingVariables) const
Lagrange interpolation/extrapolation of the coupling variables at selected time.
void createLocalVectors()
Create the local vectors of the coupling.
MapEpetra & operator+=(const MapEpetra &epetraMap)
Addition operator.
Definition: MapEpetra.cpp:198
void extrapolateCouplingVariables()
Extrapolate the values of the coupling variables for the next time step.
void importCouplingVector(multiscaleVector_Type &repeatedLocalVector, const multiscaleVector_Type &uniqueGlobalVector, const combineMode_Type &combineMode=Add)
Import the content of the unique global vector into the repeated local vector.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
void exportCouplingVector(multiscaleVector_Type &uniqueGlobalVector, const multiscaleVector_Type &repeatedLocalVector, const combineMode_Type &combineMode=Add)
Export the content of the repeated local vector into the unique global vector.
void updateInverseJacobian(const UInt &iQuadPt)
std::map< std::string, couplings_Type > multiscaleCouplingsMap
UInt modelsNumber() const
Get the number of models connected by the coupling.
std::shared_ptr< multiscaleModel_Type > multiscaleModelPtr_Type
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
virtual void insertJacobianConstantCoefficients(multiscaleMatrix_Type &jacobian)=0
Insert constant coefficients into the Jacobian matrix.
couplingVariablesContainer_Type M_localCouplingVariables
void saveSolution()
save the coupling variables information on a file
multiscaleModelsContainer_Type M_models
multiscaleVector_Type & localCouplingVariables(const UInt &id)
VectorEpetra & replace(const VectorEpetra &vector, const Int &offset)
Replace part of the vector with a given vector.
const MapEpetra & map() const
Return the MapEpetra of the vector.
MatrixEpetra< Real > multiscaleMatrix_Type
virtual void setupCouplingVariablesNumber()=0
Setup the coupling variables number.
std::vector< multiscaleModelPtr_Type > multiscaleModelsContainer_Type
bool isModelLeaderProcess(const UInt &localModelID) const
Determine if this is the model leader process.
void resetCouplingHistory()
Reset the history of the couplings.
void exportJacobian(multiscaleMatrix_Type &jacobian)
Export the Jacobian matrix.
couplingFunctionsContainer_Type M_localCouplingFunctions
multiscaleVectorPtr_Type M_localCouplingResiduals
double Real
Generic real data.
Definition: LifeV.hpp:175
multiscaleIDContainer_Type M_boundaryIDs
void showMeResiduals() const
Display the local residuals vector.
virtual void exportListOfPerturbedModels(const UInt &localCouplingVariableID, multiscaleModelsContainer_Type &perturbedModelsList)=0
Build the list of models affected by the perturbation of the local coupling variable.
bool myModel(const UInt &localModelID) const
Determine if the model is owned by this coupling.
VectorEpetra & operator*=(const data_type &scalar)
Multiplication operator.
VectorEpetra(const VectorEpetra &vector)
Copy constructor.
VectorEpetra & operator=(const VectorEpetra &vector)
Affectation operator.
virtual void setupData(const std::string &fileName)
Setup the data of the coupling.
void createCouplingMap(MapEpetra &couplingMap)
Build the global map for the coupling vectors.
MultiscaleCoupling - The Multiscale Physical Coupling.
VectorEpetra(const VectorEpetra &vector, const MapEpetraType &mapType, const combineMode_Type &combineMode)
Copy constructor.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
VectorEpetra multiscaleVector_Type
void showMe()
Display some information about the coupling.