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

Last change on this file since 6372 was 6372, checked in by Eric.Larour, 14 years ago

Simplified OutputResults module. Now also handles I/O in parallel. Not tested yet in parallel.

File size: 5.2 KB
Line 
1/*
2 * \file Elements.c
3 * \brief: implementation of the Elements class, derived from DataSet class
4 */
5
6/*Headers: {{{1*/
7#ifdef HAVE_CONFIG_H
8 #include "config.h"
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*/
27/*FUNCTION Elements::Elements(){{{1*/
28Elements::Elements(){
29 return;
30}
31/*}}}*/
32/*FUNCTION Elements::Elements(int in_enum){{{1*/
33Elements::Elements(int in_enum): DataSet(in_enum){
34 //do nothing;
35 return;
36}
37/*}}}*/
38/*FUNCTION Elements::~Elements(){{{1*/
39Elements::~Elements(){
40 return;
41}
42/*}}}*/
43
44
45
46/*Object management*/
47/*FUNCTION Elements::ProcessResultsUnits{{{1*/
48void Elements::ProcessResultsUnits(void){
49
50 int i;
51
52 //Process results to be output in the correct units
53 for(i=0;i<this->Size();i++){
54 Element* element=(Element*)this->GetObjectByOffset(i);
55 element->ProcessResultsUnits();
56 }
57}
58/*}}}*/
59/*FUNCTION Elements::DeleteResults{{{1*/
60void Elements::DeleteResults(void){
61
62 int i;
63
64 for (i=0;i<this->Size();i++){
65 Element* element=(Element*)this->GetObjectByOffset(i);
66 element->DeleteResults();
67 }
68}
69/*}}}*/
70/*FUNCTION Elements::ToResults{{{1*/
71void Elements::ToResults(Results* results,Parameters* parameters,int step, double time){
72
73 /*output: */
74 Patch* patch=NULL;
75
76 /*I/O strategy: */
77 bool io_gather=true; //the default
78
79 /*Recover parameters: */
80 parameters->FindParam(&io_gather,IoGatherEnum);
81
82
83 /*create patch object out of all results in this dataset: */
84 patch=this->ResultsToPatch();
85
86 /*Gather onto master cpu 0, if needed: */
87 #ifdef _PARALLEL_
88 if(io_gather)patch->MPI_Gather();
89 #endif
90
91 /*create result object and add to results dataset:*/
92 if (patch->maxvertices && patch->maxnodes){
93 results->AddObject(new IntExternalResult(results->Size()+1,PatchVerticesEnum,patch->maxvertices,step,time));
94 results->AddObject(new IntExternalResult(results->Size()+1,PatchNodesEnum, patch->maxnodes,step,time));
95 results->AddObject(new DoubleMatExternalResult(results->Size()+1,PatchEnum,patch->values,patch->numrows,patch->numcols,step,time));
96 }
97
98 /*Free ressources:*/
99 delete patch;
100
101}
102/*}}}*/
103/*FUNCTION Elements::ResultsToPatch{{{1*/
104Patch* Elements::ResultsToPatch(void){
105
106 /*output: */
107 Patch* patch=NULL;
108
109 /*intermediary: */
110 int i;
111 int count;
112 int numrows;
113 int numvertices;
114 int numnodes;
115 int max_numvertices;
116 int max_numnodes;
117 int element_numvertices;
118 int element_numrows;
119 int element_numnodes;
120
121 /*We are going to extract from the results within the elements, the desired results , and create a table
122 * of patch information, that will hold, for each element that computed the result that
123 * 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
124 * at the nodes (could be different from the vertices). This will be used for visualization purposes.
125 * For example, we could build the following patch table, for velocities:
126 *
127 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
128 VxEnum 1 .5 1 P0 1 2 4.5 NaN NaN
129 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
130 VzEnum 2 .8 2 P1 1 3 4 4.5 3.2 2.5
131 * ... etc ...
132 *
133 * So what do we need to build the table: the maximum number of vertices included in the table,
134 * and the maximum number of nodal values, as well as the number of rows. Once we have that,
135 * we ask the elements to fill their own row in the table, by looping on the elememnts.
136 *
137 * We will use the Patch object, which will store all of the information needed, and will be able
138 * to output itself to disk on its own. See object/Patch.h for format of this object.*/
139
140 /*First, determine maximum number of vertices, nodes, and number of results: */
141 numrows=0;
142 numvertices=0;
143 numnodes=0;
144
145 for(i=0;i<this->Size();i++){
146
147 Element* element=(Element*)this->GetObjectByOffset(i);
148 element->PatchSize(&element_numrows,&element_numvertices,&element_numnodes);
149
150 numrows+=element_numrows;
151 if(element_numvertices>numvertices)numvertices=element_numvertices;
152 if(element_numnodes>numnodes)numnodes=element_numnodes;
153 }
154
155 #ifdef _PARALLEL_
156 /*Synchronize across cluster, so as to not end up with different sizes for each patch on each cpu: */
157 MPI_Reduce (&numvertices,&max_numvertices,1,MPI_INT,MPI_MAX,0,MPI_COMM_WORLD );
158 MPI_Bcast(&max_numvertices,1,MPI_INT,0,MPI_COMM_WORLD);
159 numvertices=max_numvertices;
160
161 MPI_Reduce (&numnodes,&max_numnodes,1,MPI_INT,MPI_MAX,0,MPI_COMM_WORLD );
162 MPI_Bcast(&max_numnodes,1,MPI_INT,0,MPI_COMM_WORLD);
163 numnodes=max_numnodes;
164 #endif
165
166 /*Ok, initialize Patch object: */
167 patch=new Patch(numrows,numvertices,numnodes);
168
169 /*Now, go through elements, and fill the Patch object: */
170 count=0;
171 for(i=0;i<this->Size();i++){
172 Element* element=(Element*)this->GetObjectByOffset(i);
173 element->PatchFill(&count,patch);
174 }
175
176 return patch;
177
178}
179/*}}}*/
Note: See TracBrowser for help on using the repository browser.