[4216] | 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 |
|
---|
| 23 | using namespace std;
|
---|
| 24 | /*}}}*/
|
---|
| 25 |
|
---|
| 26 | /*Object constructors and destructor*/
|
---|
| 27 | /*FUNCTION Elements::Elements(){{{1*/
|
---|
| 28 | Elements::Elements(){
|
---|
| 29 | return;
|
---|
| 30 | }
|
---|
| 31 | /*}}}*/
|
---|
| 32 | /*FUNCTION Elements::Elements(int in_enum){{{1*/
|
---|
| 33 | Elements::Elements(int in_enum): DataSet(in_enum){
|
---|
| 34 | //do nothing;
|
---|
| 35 | return;
|
---|
| 36 | }
|
---|
| 37 | /*}}}*/
|
---|
| 38 | /*FUNCTION Elements::~Elements(){{{1*/
|
---|
| 39 | Elements::~Elements(){
|
---|
| 40 | return;
|
---|
| 41 | }
|
---|
| 42 | /*}}}*/
|
---|
| 43 |
|
---|
[6372] | 44 |
|
---|
| 45 |
|
---|
[4216] | 46 | /*Object management*/
|
---|
[6372] | 47 | /*FUNCTION Elements::ProcessResultsUnits{{{1*/
|
---|
| 48 | void 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*/
|
---|
| 60 | void 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*/
|
---|
| 71 | void 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*/
|
---|
| 104 | Patch* 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 | /*}}}*/
|
---|