1 | |
---|
2 | #ifndef __FIELD_IMPL_HPP__ |
---|
3 | #define __FIELD_IMPL_HPP__ |
---|
4 | |
---|
5 | #include "xios_spl.hpp" |
---|
6 | #include "field.hpp" |
---|
7 | #include "context.hpp" |
---|
8 | #include "grid.hpp" |
---|
9 | #include "timer.hpp" |
---|
10 | #include "array_new.hpp" |
---|
11 | |
---|
12 | |
---|
13 | namespace xios { |
---|
14 | |
---|
15 | template <int N> |
---|
16 | void CField::setData(const CArray<double, N>& _data) |
---|
17 | TRY |
---|
18 | { |
---|
19 | if (modelToClientSourceFilter_) |
---|
20 | { |
---|
21 | if (check_if_active.isEmpty() || (!check_if_active.isEmpty() && (!check_if_active) || isActive(true))) |
---|
22 | { |
---|
23 | if ( info.getLevel()>100 ) |
---|
24 | { |
---|
25 | const double* array = _data.dataFirst(); |
---|
26 | int numElements( _data.numElements() ); |
---|
27 | checkSumLike( array, numElements, true ); |
---|
28 | } |
---|
29 | modelToClientSourceFilter_->streamData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data); |
---|
30 | } |
---|
31 | } |
---|
32 | else if (instantDataFilter) |
---|
33 | ERROR("void CField::setData(const CArray<double, N>& _data)", |
---|
34 | << "Impossible to receive data from the model for a field [ id = " << getId() << " ] with a reference or an arithmetic operation."); |
---|
35 | } |
---|
36 | CATCH_DUMP_ATTR |
---|
37 | |
---|
38 | |
---|
39 | template <int N> |
---|
40 | void CField::getData(CArray<double, N>& _data) const |
---|
41 | TRY |
---|
42 | { |
---|
43 | if (clientToModelStoreFilter_) |
---|
44 | { |
---|
45 | CDataPacket::StatusCode status = clientToModelStoreFilter_->getData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data); |
---|
46 | if ( info.getLevel()>100 ) |
---|
47 | { |
---|
48 | const double* array = _data.dataFirst(); |
---|
49 | int numElements( _data.numElements() ); |
---|
50 | checkSumLike( array, numElements, false ); |
---|
51 | } |
---|
52 | |
---|
53 | if (status == CDataPacket::END_OF_STREAM) |
---|
54 | ERROR("void CField::getData(CArray<double, N>& _data) const", |
---|
55 | << "Impossible to access field data, all the records of the field [ id = " << getId() << " ] have been already read."); |
---|
56 | } |
---|
57 | else |
---|
58 | { |
---|
59 | ERROR("void CField::getData(CArray<double, N>& _data) const", |
---|
60 | << "Impossible to access field data, the field [ id = " << getId() << " ] does not have read access."); |
---|
61 | } |
---|
62 | } |
---|
63 | CATCH |
---|
64 | |
---|
65 | void CField::checkSumLike( const double* array, int numElements, bool output ) const |
---|
66 | { |
---|
67 | int rk = CContext::getCurrent()->getIntraCommRank(); |
---|
68 | int sz = CContext::getCurrent()->getIntraCommSize(); |
---|
69 | MPI_Comm comm = CContext::getCurrent()->getIntraComm(); |
---|
70 | |
---|
71 | double localSum( 0. ); |
---|
72 | double error( 0. ); |
---|
73 | unsigned long long checkSum( 0 ); |
---|
74 | for ( int i=0 ; i<numElements ; i++ ) { |
---|
75 | bool contributes( true ); |
---|
76 | if ( (!output) && ( !default_value.isEmpty() ) ) |
---|
77 | { |
---|
78 | if ( fabs(array[i]) > 0) |
---|
79 | if ( fabs(array[i]-default_value.getValue())/array[i] < 2e-16 ) |
---|
80 | contributes = false; |
---|
81 | } |
---|
82 | if (contributes) |
---|
83 | { |
---|
84 | double y = array[i] - error; |
---|
85 | double t = localSum + y; |
---|
86 | error = (t - localSum) - y; |
---|
87 | localSum = t; |
---|
88 | |
---|
89 | checkSum += *((unsigned long long*)(&array[i])); |
---|
90 | checkSum = checkSum%LLONG_MAX; |
---|
91 | } |
---|
92 | } |
---|
93 | |
---|
94 | double globalSum( 0. ); |
---|
95 | unsigned long long globalCheck( 0 ); |
---|
96 | |
---|
97 | if ( rk ==0 ) |
---|
98 | { |
---|
99 | MPI_Status status; |
---|
100 | globalSum = localSum; // rank 0 contribution |
---|
101 | globalCheck = checkSum; |
---|
102 | for ( int irk = 1 ; irk < sz ; irk++ ) |
---|
103 | { |
---|
104 | MPI_Recv( &localSum, 1, MPI_DOUBLE, irk, 0, comm, &status ); |
---|
105 | double y = localSum - error; |
---|
106 | double t = globalSum + y; |
---|
107 | error = (t - globalSum) - y; |
---|
108 | globalSum = t; |
---|
109 | |
---|
110 | MPI_Recv( &checkSum, 1, MPI_UNSIGNED_LONG_LONG, irk, 1, comm, &status ); |
---|
111 | globalCheck += checkSum; |
---|
112 | globalCheck = globalCheck%LLONG_MAX; |
---|
113 | } |
---|
114 | } |
---|
115 | else |
---|
116 | { |
---|
117 | MPI_Send( &localSum, 1, MPI_DOUBLE, 0, 0, comm ); |
---|
118 | MPI_Send( &checkSum, 1, MPI_UNSIGNED_LONG_LONG, 0, 1, comm ); |
---|
119 | } |
---|
120 | |
---|
121 | if ( rk == 0 ) |
---|
122 | { |
---|
123 | info(100) << setprecision(DBL_DIG); |
---|
124 | if (output ) |
---|
125 | info(100) << "Check Output key field for : " << getId() << ", key = " << globalCheck << ", sum = " << globalSum << endl; |
---|
126 | else |
---|
127 | info(100) << "Check Input key field for : " << getId() << ", key = " << globalCheck << ", sum = " << globalSum << endl; |
---|
128 | info(100) << setprecision(6); |
---|
129 | } |
---|
130 | } |
---|
131 | |
---|
132 | } // namespace xios |
---|
133 | |
---|
134 | #endif |
---|