source: issm/trunk/src/c/Container/Elements.cpp@ 13975

Last change on this file since 13975 was 13975, checked in by Mathieu Morlighem, 12 years ago

merged trunk-jpl and trunk for revision 13974

File size: 11.2 KB
RevLine 
[4216]1/*
2 * \file Elements.c
3 * \brief: implementation of the Elements class, derived from DataSet class
4 */
5
[12706]6/*Headers: {{{*/
[4216]7#ifdef HAVE_CONFIG_H
[9320]8 #include <config.h>
[4216]9#else
10#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
11#endif
12
13#include <vector>
14#include <functional>
15#include <algorithm>
16#include <iostream>
17
18#include "./DataSet.h"
19#include "../shared/shared.h"
20#include "../include/include.h"
21#include "../EnumDefinitions/EnumDefinitions.h"
22
23using namespace std;
24/*}}}*/
25
26/*Object constructors and destructor*/
[12706]27/*FUNCTION Elements::Elements(){{{*/
[4216]28Elements::Elements(){
[10522]29 enum_type=MeshElementsEnum;
[4216]30 return;
31}
32/*}}}*/
[12706]33/*FUNCTION Elements::~Elements(){{{*/
[4216]34Elements::~Elements(){
35 return;
36}
37/*}}}*/
38
39/*Object management*/
[12706]40/*FUNCTION Elements::Configure{{{*/
[6411]41void Elements::Configure(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters){
42
43 vector<Object*>::iterator object;
44 Element* element=NULL;
45
46 for ( object=objects.begin() ; object < objects.end(); object++ ){
47
[13975]48 element=dynamic_cast<Element*>((*object));
[6411]49 element->Configure(elements,loads,nodes,materials,parameters);
50
51 }
52
53}
54/*}}}*/
[12706]55/*FUNCTION Elements::ProcessResultsUnits{{{*/
[6372]56void Elements::ProcessResultsUnits(void){
57
58 //Process results to be output in the correct units
[6411]59 for(int i=0;i<this->Size();i++){
[13975]60 Element* element=dynamic_cast<Element*>(this->GetObjectByOffset(i));
[6372]61 element->ProcessResultsUnits();
62 }
63}
64/*}}}*/
[12706]65/*FUNCTION Elements::DeleteResults{{{*/
[6372]66void Elements::DeleteResults(void){
[13975]67
[6411]68 for (int i=0;i<this->Size();i++){
[13975]69 Element* element=dynamic_cast<Element*>(this->GetObjectByOffset(i));
[6372]70 element->DeleteResults();
71 }
72}
73/*}}}*/
[12706]74/*FUNCTION Elements::ResultsToPatch{{{*/
[6372]75Patch* Elements::ResultsToPatch(void){
76
77 /*output: */
78 Patch* patch=NULL;
79
80 /*intermediary: */
81 int i;
82 int count;
83 int numrows;
84 int numvertices;
85 int numnodes;
86 int max_numvertices;
87 int max_numnodes;
88 int element_numvertices;
89 int element_numrows;
90 int element_numnodes;
91
92 /*We are going to extract from the results within the elements, the desired results , and create a table
93 * of patch information, that will hold, for each element that computed the result that
94 * we desire, the enum_type of the result, the step and time, the id of the element, the interpolation type, the vertices ids, and the values
95 * at the nodes (could be different from the vertices). This will be used for visualization purposes.
96 * For example, we could build the following patch table, for velocities:
97 *
98 1. on a Beam element, Vx, at step 1, time .5, element id 1, interpolation type P0 (constant), vertices ids 1 and 2, one constant value 4.5
99 VxEnum 1 .5 1 P0 1 2 4.5 NaN NaN
100 2. on a Tria element, Vz, at step 2, time .8, element id 2, interpolation type P1 (linear), vertices ids 1 3 and 4, with values at 3 nodes 4.5, 3.2, 2.5
101 VzEnum 2 .8 2 P1 1 3 4 4.5 3.2 2.5
102 * ... etc ...
103 *
104 * So what do we need to build the table: the maximum number of vertices included in the table,
105 * and the maximum number of nodal values, as well as the number of rows. Once we have that,
106 * we ask the elements to fill their own row in the table, by looping on the elememnts.
107 *
108 * We will use the Patch object, which will store all of the information needed, and will be able
109 * to output itself to disk on its own. See object/Patch.h for format of this object.*/
[13975]110
[6372]111 /*First, determine maximum number of vertices, nodes, and number of results: */
112 numrows=0;
113 numvertices=0;
114 numnodes=0;
115
116 for(i=0;i<this->Size();i++){
117
[13975]118 Element* element=dynamic_cast<Element*>(this->GetObjectByOffset(i));
[6372]119 element->PatchSize(&element_numrows,&element_numvertices,&element_numnodes);
120
121 numrows+=element_numrows;
122 if(element_numvertices>numvertices)numvertices=element_numvertices;
123 if(element_numnodes>numnodes)numnodes=element_numnodes;
124 }
125
126 /*Synchronize across cluster, so as to not end up with different sizes for each patch on each cpu: */
[12330]127 #ifdef _HAVE_MPI_
[13975]128 MPI_Reduce (&numvertices,&max_numvertices,1,MPI_INT,MPI_MAX,0,IssmComm::GetComm() );
129 MPI_Bcast(&max_numvertices,1,MPI_INT,0,IssmComm::GetComm());
[6372]130 numvertices=max_numvertices;
131
[13975]132 MPI_Reduce (&numnodes,&max_numnodes,1,MPI_INT,MPI_MAX,0,IssmComm::GetComm() );
133 MPI_Bcast(&max_numnodes,1,MPI_INT,0,IssmComm::GetComm());
[6372]134 numnodes=max_numnodes;
135 #endif
136
137 /*Ok, initialize Patch object: */
138 patch=new Patch(numrows,numvertices,numnodes);
139
140 /*Now, go through elements, and fill the Patch object: */
141 count=0;
142 for(i=0;i<this->Size();i++){
[13975]143 Element* element=dynamic_cast<Element*>(this->GetObjectByOffset(i));
[6372]144 element->PatchFill(&count,patch);
145 }
146
147 return patch;
148}
149/*}}}*/
[12706]150/*FUNCTION Elements::SetCurrentConfiguration{{{*/
[6411]151void Elements::SetCurrentConfiguration(Elements* elements,Loads* loads, Nodes* nodes, Vertices* vertices, Materials* materials,Parameters* parameters){
152
153 vector<Object*>::iterator object;
154 Element* element=NULL;
155
156 for ( object=objects.begin() ; object < objects.end(); object++ ){
157
[13975]158 element=dynamic_cast<Element*>((*object));
[6411]159 element->SetCurrentConfiguration(elements,loads,nodes,materials,parameters);
160
161 }
162
163}
164/*}}}*/
[12706]165/*FUNCTION Elements::ToResults{{{*/
[11027]166void Elements::ToResults(Results* results,Parameters* parameters){
[6411]167
[13975]168 int my_rank;
169 int num_procs;
[9878]170
[13975]171 Patch *patch = NULL;
172 int *resultsenums = NULL;
173 int *resultssizes = NULL;
174 int *resultssteps = NULL;
175 IssmDouble *resultstimes = NULL;
176 IssmDouble *vector_serial = NULL;
177 Vector<IssmDouble> *vector = NULL;
178 bool io_gather;
179 bool results_as_patches;
180 int numberofvertices ,numberofelements;
181 int numberofresults ,vectorsize;
182 int rank;
183 int minrank;
[6411]184
[13975]185 /*recover my_rank:*/
186 my_rank=IssmComm::GetRank();
187 num_procs=IssmComm::GetSize();
188
[6411]189 /*Recover parameters: */
[9622]190 parameters->FindParam(&io_gather,SettingsIoGatherEnum);
[10981]191 parameters->FindParam(&results_as_patches,SettingsResultsAsPatchesEnum);
[9874]192 parameters->FindParam(&numberofvertices,MeshNumberofverticesEnum);
[11027]193 parameters->FindParam(&numberofelements,MeshNumberofelementsEnum);
[6411]194
[10981]195 if(!results_as_patches){
[9874]196 /*No patch here, we prepare vectors*/
[6411]197
[11239]198 /*Get rank of first cpu that has results*/
[12330]199 #ifdef _HAVE_MPI_
[11239]200 if(this->Size()) rank=my_rank;
201 else rank=num_procs;
[13975]202 MPI_Allreduce (&rank,&minrank,1,MPI_INT,MPI_MIN,IssmComm::GetComm());
[12330]203 #else
204 minrank=my_rank;
205 #endif
[11239]206
[11027]207 /*see what the first element of this partition has in stock (this is common to all partitions)*/
[11239]208 if(my_rank==minrank){
[13395]209 if(this->Size()==0) _error_("Cannot write results because there is no element??");
[13975]210 Element* element=dynamic_cast<Element*>(this->GetObjectByOffset(0));
[11027]211 element->ListResultsInfo(&resultsenums,&resultssizes,&resultstimes,&resultssteps,&numberofresults);
212 }
[12330]213 #ifdef _HAVE_MPI_
[13975]214 MPI_Bcast(&numberofresults,1,MPI_DOUBLE,minrank,IssmComm::GetComm());
[12330]215 #endif
[11239]216
[11027]217 /*Get out if there is no results. Otherwise broadcast info*/
218 if(!numberofresults) return;
[12330]219 #ifdef _HAVE_MPI_
[11239]220 if(my_rank!=minrank){
[12706]221 resultsenums=xNew<int>(numberofresults);
222 resultssizes=xNew<int>(numberofresults);
223 resultstimes=xNew<IssmDouble>(numberofresults);
224 resultssteps=xNew<int>(numberofresults);
[11027]225 }
[13975]226 MPI_Bcast(resultsenums,numberofresults,MPI_INT,minrank,IssmComm::GetComm());
227 MPI_Bcast(resultssizes,numberofresults,MPI_INT,minrank,IssmComm::GetComm());
228 MPI_Bcast(resultstimes,numberofresults,MPI_DOUBLE,minrank,IssmComm::GetComm());
229 MPI_Bcast(resultssteps,numberofresults,MPI_INT,minrank,IssmComm::GetComm());
[12330]230 #endif
[11027]231
[9874]232 /*Loop over all results and get nodal vector*/
233 for(int i=0;i<numberofresults;i++){
234
235 /*Get vector for result number i*/
[11027]236 if(resultssizes[i]==P1Enum) vectorsize=numberofvertices;
237 else if(resultssizes[i]==P0Enum) vectorsize=numberofelements;
[13395]238 else _error_("Unkown result size: " << EnumToStringx(resultssizes[i]));
239 vector=new Vector<IssmDouble>(vectorsize);
[11027]240
[9874]241 for(int j=0;j<this->Size();j++){
[13975]242 Element* element=dynamic_cast<Element*>(this->GetObjectByOffset(j));
[12630]243 element->GetVectorFromResults(vector,i,resultsenums[i],resultssizes[i]);
[9874]244 }
[11995]245 vector->Assemble();
[9874]246
247 /*Serialize and add to results*/
[11995]248 vector_serial=vector->ToMPISerial();
[9878]249 if(my_rank==0){
[9879]250 /*No need to add this vector for all cpus*/
[13395]251 #ifdef _HAVE_ADOLC_
252 IssmPDouble* vector_serial_passive=xNew<IssmPDouble>(vectorsize);
253 for(int k=0;k<vectorsize;k++)vector_serial_passive[k]=reCast<IssmPDouble>(vector_serial[k]);
254 results->AddObject(new GenericExternalResult<double*>(results->Size()+1,resultsenums[i],vector_serial_passive,vectorsize,1,resultssteps[i],resultstimes[i]));
255 xDelete<IssmPDouble>(vector_serial_passive);
256 #else
257 results->AddObject(new GenericExternalResult<double*>(results->Size()+1,resultsenums[i],vector_serial,vectorsize,1,resultssteps[i],resultstimes[i]));
258 #endif
[9878]259 }
[9874]260
261 /*clean up*/
[11995]262 xdelete(&vector);
[12706]263 xDelete<IssmDouble>(vector_serial);
[9874]264 }
265 }
266 else{
267 /*create patch object out of all results in this dataset: */
268 patch=this->ResultsToPatch();
269
270 /*Gather onto master cpu 0, if needed: */
271 if(io_gather)patch->Gather();
[6411]272
[9874]273 /*create result object and add to results dataset:*/
274 if (patch->maxvertices && patch->maxnodes){
[13395]275 results->AddObject(new GenericExternalResult<int>(results->Size()+1,PatchVerticesEnum,patch->maxvertices,1,0));
276 results->AddObject(new GenericExternalResult<int>(results->Size()+1,PatchNodesEnum, patch->maxnodes,1,0));
277 #ifdef _HAVE_ADOLC_
278 IssmPDouble* values_passive=xNew<IssmPDouble>(patch->numrows*patch->numcols);
279 for(int k=0;k<(patch->numrows*patch->numcols);k++)values_passive[k]=reCast<IssmPDouble>(patch->values[k]);
280 results->AddObject(new GenericExternalResult<double*>(results->Size()+1,PatchEnum, values_passive,patch->numrows,patch->numcols,1,0));
281 xDelete<IssmPDouble>(values_passive);
282 #else
283 results->AddObject(new GenericExternalResult<double*>(results->Size()+1,PatchEnum, patch->values,patch->numrows,patch->numcols,1,0));
284 #endif
[9874]285 }
[6411]286 }
287
288 /*Free ressources:*/
[12706]289 xDelete<int>(resultsenums);
290 xDelete<int>(resultssizes);
291 xDelete<int>(resultssteps);
292 xDelete<IssmDouble>(resultstimes);
[6411]293 delete patch;
294}
295/*}}}*/
[13975]296/*FUNCTION Elements::MaxNumNodes{{{*/
297int Elements::MaxNumNodes(void){
298
299 int max=0;
300 int allmax;
301 int numnodes=0;
302
303 /*Now go through all elements, and get how many nodes they own, unless they are clone nodes: */
304 for(int i=0;i<this->Size();i++){
305
306 Element* element=dynamic_cast<Element*>(this->GetObjectByOffset(i));
307 numnodes=element->GetNumberOfNodes();
308 if(numnodes>max)max=numnodes;
309 }
310
311 /*Grab max of all cpus: */
312 #ifdef _HAVE_MPI_
313 MPI_Allreduce((void*)&max,(void*)&allmax,1,MPI_INT,MPI_MAX,IssmComm::GetComm());
314 max=allmax;
315 #endif
316
317 return max;
318}
319/*}}}*/
[12706]320/*FUNCTION Elements::NumberOfElements{{{*/
[7089]321int Elements::NumberOfElements(void){
322
[13975]323 int local_nelem;
[7089]324 int numberofelements;
325
326 local_nelem=this->Size();
[12330]327 #ifdef _HAVE_MPI_
[13975]328 MPI_Allreduce ( (void*)&local_nelem,(void*)&numberofelements,1,MPI_INT,MPI_SUM,IssmComm::GetComm());
[7089]329 #else
[12330]330 numberofelements=local_nelem;
[7089]331 #endif
332
333 return numberofelements;
334}
335/*}}}*/
[12706]336/*FUNCTION Elements::InputCopy{{{*/
[8967]337void Elements::InputDuplicate(int input_enum,int output_enum){
338
[9211]339 for(int i=0;i<this->Size();i++){
[13975]340 Element* element=dynamic_cast<Element*>(this->GetObjectByOffset(i));
[8967]341 element->InputDuplicate(input_enum,output_enum);
342 }
343}
344/*}}}*/
Note: See TracBrowser for help on using the repository browser.