GCC Code Coverage Report


Directory: ./
File: Model/cvgMainSlave.hpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 0 48 0.0%
Branches: 0 38 0.0%

Line Branch Exec Source
1 // ______ ______ _ _ _____ ______
2 // | ____| ____| | (_)/ ____| | ____|
3 // | |__ | |__ | | _| (___ ___| |__
4 // | __| | __| | | | |\___ \ / __| __|
5 // | | | |____| |____| |____) | (__| |____
6 // |_| |______|______|_|_____/ \___|______|
7 // Finite Elements for Life Sciences and Engineering
8 //
9 // License: LGL2.1 License
10 // FELiScE default license: LICENSE in root folder
11 //
12 // Main authors: M. Aletti
13 //
14
15 #if FELISCE_WITH_CVGRAPH
16 #ifndef _CVGMAINSLAVE_HPP
17 #define _CVGMAINSLAVE_HPP
18
19 // System includes
20
21 // External includes
22
23 // Project includes
24 #include "Graph/cvgraph.hpp"
25 #include "MessageInterface/messageAdm.hpp"
26 #include "Solver/linearProblem.hpp"
27 #include "PETScInterface/petscMatrix.hpp"
28 #include "Core/chrono.hpp"
29
30 using namespace cvgraph;
31
32 /*!
33 \file cvgMainSlave.hpp
34 \authors M. Aletti
35 \date Oct 2016
36 \brief cvgMainSlave class.
37
38 This class is meant to be a wrapper of the cvgraph utilities.
39 This class can be used (and compiled) only when the flag FELISCE_WITHCVGRAPH
40 is activated.
41 The class is meant to work correctly in parallel, however the communications
42 and the interpolation are done only by the master.
43 This parallel/sequential difference should be handled inside the class.
44 From outside this class should be considered as parallel.
45
46 This object is associated to a compartment (node) of the graph.
47
48 TODO:
49 1. change the name from cvgMainSlave to something better.
50 2. the class contains a pointer to a linear problem. What if we want to use a felisce model that contains two linear problems?
51 */
52 namespace felisce
53 {
54 class cvgMainSlave
55 {
56 private:
57 // The empty constructor is removed.
58 cvgMainSlave();
59 public:
60 // Constructor
61 cvgMainSlave(int argc, char ** argv);
62 //Sending time before exchanging initial condition
63 void exchangeInitialCondition();
64 // To build m_interpolator matrix, and exchange interface information.
65 void buildInterpolator(LinearProblem* pt);
66 // First contact with the master
67 void firstContact();
68 // Interpolate the data and send them
69 void sendData(std::vector<PetscVector>& sequentialVolumeVectors, std::size_t iConn);
70 // just receive them
71 void receiveData(std::vector<PetscVector>& sequentialVolumeVectors, std::size_t iConn);
72 // update time iteration in the case of a new time step
73 void printIteration(int& timeIteration);
74
75 // Useful functions to check the time status.
76 inline bool newTimeStep() const {
77 return this->checkTimeStatus(cvgraph::CVG_TIME_STATUS_NEW_TIME_STEP);
78 }
79 inline bool redoTimeStep() const {
80 return this->checkTimeStatus(cvgraph::CVG_TIME_STATUS_REDO_TIME_STEP);
81 }
82 inline bool redoTimeStepOnlyCVGData() const {
83 return this->checkTimeStatus(cvgraph::CVG_TIME_STATUS_REDO_TIME_STEP_ONLY_CVGDATA);
84 }
85 inline bool stop() const {
86 return this->checkTimeStatus(cvgraph::CVG_TIME_STATUS_STOP);
87 }
88 inline const std::vector<int>& interfaceLabels(std::size_t iConn) const {
89 return m_interfaceLabels[iConn];
90 }
91 // Getters
92 inline const MessageInfo& msgInfo() const {
93 return m_msgInfo;
94 }
95 inline const CVGraphParam& cvgParam() const {
96 return CVGraphParam::instance();
97 }
98 inline std::size_t numVarToRead(std::size_t iConn) const {
99 return m_numVarToRead[iConn];
100 }
101 inline std::size_t numVarToSend(std::size_t iConn) const {
102 return m_numVarToSend[iConn];
103 }
104 inline const std::string& sendVariable(std::size_t iConn, std::size_t cVar) const {
105 FEL_ASSERT(iConn<m_sendVariables.size());
106 FEL_ASSERT(cVar<m_sendVariables[iConn].size());
107 return m_sendVariables[iConn][cVar];
108 }
109 inline const std::string& readVariable(std::size_t iConn, std::size_t cVar) const {
110 return m_readVariables[iConn][cVar];
111 }
112 inline std::size_t numConnections() const {
113 return m_numOfNeighbours;
114 }
115 inline std::size_t residualInterpolationType(std::size_t iConn) const {
116 return m_residualInterpolationType[iConn];
117 }
118
119 bool initialConditionNeeded( std::size_t iConn ) const;
120
121 // Ids
122 std::size_t iConn(std::size_t IdConn) const {
123 return m_iConnFromIds.at(IdConn);
124 }
125 std::size_t IdConn(std::size_t iConn) const {
126 return m_IdsOfConnections[iConn];
127 }
128
129 void print() const;
130 private:
131 // Data of the compartment
132 int m_cmptId; // id of the current compartment in the graph
133 std::string m_cmptName; // its name
134 LinearProblem* m_lpb; // its linear problem
135
136 // General cvg info
137 CVGraph m_cvg; // the graph
138 int m_protocol; // protocol
139 MessageInfo m_msgInfo; // message info
140 MessageAdm* m_msg; // ptr to the message administrator
141 int m_verbose; // cvgraph verbosity level
142
143 // COMMENT ON THE IDs.
144 // the current compartment has m_numOfNeighbours neighbours.
145 // Each of these compartments is connected to the current one via one connections.
146 //
147 // Inside this class iConn and iCmpt take values in 0...m_numOfNeighbours - 1 and are interchangeable.
148 // However, in the global graph each compartment is described by a different ids in 0...NUM OF NODES
149 // Similarly there are ids for the connections in 0...NUM OF EDGES
150 // Consider that NUM OF NODES != NUM OF EDGES.
151 //
152 // Finally consider that in cvgraph the so-called descriptor are used to identify a connection-edge or a compartment-node.
153 // These are object of the boost library and they can be obtained from the Ids through some utility functions in cvgraph.
154 std::size_t m_numOfNeighbours; // the number of nodes that are connected to it
155 std::vector<std::size_t> m_IdsOfOtherCompartments; // the ids of those nodes in the graph
156 std::vector<std::size_t> m_IdsOfConnections; // the ids of the corresponding connections
157 std::map<std::size_t,std::size_t> m_iConnFromIds; // inverse of the std::vector above
158
159
160 // For each connection we have an interpolator
161 std::vector<PetscMatrix*> m_interpolator; // interpolator matrix from this compartments to another one
162 std::vector<PetscMatrix*> m_interpolatorBackward; // interpolator matrix from another compartment to this one. (its transpose has the same dimension as the interpolator
163
164 std::vector<std::vector<int> > m_interfaceLabels; // for each connection, the list of the surface label of the interface
165
166 std::vector<CVGraphData*> m_data_recv;
167 std::vector<CVGraphData*> m_data_send;
168
169 std::vector<int> m_dimOfDataToReceive; //ncols;
170 std::vector<int> m_dimOfDataToSend; //nrows;
171
172 std::vector<PetscVector> m_dataSendPreInterpolation;
173 std::vector<PetscVector> m_dataSend;
174
175 bool checkTimeStatus( const cvgraph::CVGStatus flag) const;
176 void checkCustomFileCompleted( std::string keyword, std::size_t iBD ) const;
177 void customFileCompleted( std::string keyword, std::size_t iBD ) const;
178 std::string fileName(std::string keyword, std::size_t iConn, std::string readOrWrite, std::string folder="") const;
179 ChronoInstance::Pointer m_receiveChronoPtr;
180
181 // For each connection, this compartment knows which variable (denoted by a std::string) has to be sent or read.
182 // depending on this the user can make the different choices.
183 // These to functions are private because the user is not supposed to use them, he should use the getters sendVariable/readVariable
184 std::string variableToSend( int IdConn, std::size_t cVar ) {
185 return m_cvg.graph()[m_cvg.connectDescriptor( IdConn ) ].toBeSentVariable(m_cmptName, cVar);
186 }
187 std::string variableToRead( int IdConn, std::size_t cVar ) {
188 return m_cvg.graph()[m_cvg.connectDescriptor( IdConn ) ].toBeReadVariable(m_cmptName, cVar);
189 }
190 std::vector<std::size_t> m_numVarToRead, m_numVarToSend;
191 std::vector<std::vector<std::string> > m_sendVariables, m_readVariables;
192
193 // id of the variable which has to be passed. For instance 0 for velocity in NS. If we wanted for some reason to couple the pressure it should be one
194 std::vector<std::size_t> m_IdsOfVarToExchange; // It is std::vector because in principle we could couple more than one variable at the same time (think about poro elasticity, where could couple displacement, but also the flow). For now, it has been always used as a scalar.
195
196 void handleCouplingVariablesAndOverwriteBC();
197 std::vector<int> m_residualInterpolationType;
198 void exchangeBackwardInterpolators();
199
200 public:
201 // Utility functions to classify the nature of the BCs on a given connection
202
203 // Wether we need to sum the residual directly in the RHS.
204 // This happend for neumann and for robin conditions, but only when the residualInterpType == 1
205 inline bool sumDirectlyIntoRHS(std::size_t iConn) const {
206 return ( neumann(iConn) || robin(iConn) ) && m_residualInterpolationType[iConn] == 1;
207 }
208 // neumann bondary condition, one variable to read and of type neumann
209 inline bool neumann(std::size_t iConn) const {
210 return m_numVarToRead[iConn] == 1 && CVGraph::neumannTypeVariable(m_readVariables[iConn][0]);
211 }
212 // dirichlet bondary condition, one variable to read and of type dirichlet
213 inline bool dirichlet(std::size_t iConn) const {
214 return m_numVarToRead[iConn] == 1 && CVGraph::dirichletTypeVariable(m_readVariables[iConn][0]);
215 }
216 // robin boundary condition, two variables to read.
217 inline bool robin(std::size_t iConn) const {
218 return m_numVarToRead[iConn] == 2;
219 }
220 // returns the neumann of the boundary condition if it is of neumann or robin type
221 // if it is of dirichlet type it returns "Error"
222 std::string neumannVariable(std::size_t iConn) const;
223
224 // return true if there is at least one dirichlet condition
225 inline bool thereIsAtLeastOneDirichletCondition() const {
226 return thereIsAtLeastOneConditionOfType(&cvgMainSlave::dirichlet);
227 }
228 // return true if there is at least one robin condition
229 inline bool thereIsAtLeastOneRobinCondition() const {
230 return thereIsAtLeastOneConditionOfType(&cvgMainSlave::robin);
231 }
232 // return true if there is at least one neumann condition
233 inline bool thereIsAtLeastOneNeumannCondition() const {
234 return thereIsAtLeastOneConditionOfType(&cvgMainSlave::neumann);
235 }
236 inline bool thereIsAtLeastOneNaturalCondition() const {
237 return thereIsAtLeastOneNeumannCondition() || thereIsAtLeastOneRobinCondition();
238 }
239 private:
240 // return true if there is at least one connection satisfying the function test.
241 bool thereIsAtLeastOneConditionOfType(bool(cvgMainSlave::*test)(std::size_t) const) const;
242 };
243 }
244 #endif
245 #endif
246