[352] | 1 | |
---|
| 2 | #ifndef __FIELD_IMPL_HPP__ |
---|
| 3 | #define __FIELD_IMPL_HPP__ |
---|
| 4 | |
---|
[591] | 5 | #include "xios_spl.hpp" |
---|
[352] | 6 | #include "field.hpp" |
---|
| 7 | #include "context.hpp" |
---|
| 8 | #include "grid.hpp" |
---|
| 9 | #include "timer.hpp" |
---|
[369] | 10 | #include "array_new.hpp" |
---|
[2465] | 11 | #include <cfloat> |
---|
[352] | 12 | |
---|
| 13 | namespace xios { |
---|
| 14 | |
---|
[459] | 15 | template <int N> |
---|
| 16 | void CField::setData(const CArray<double, N>& _data) |
---|
[1622] | 17 | TRY |
---|
[459] | 18 | { |
---|
[1930] | 19 | if (modelToClientSourceFilter_) |
---|
[1201] | 20 | { |
---|
| 21 | if (check_if_active.isEmpty() || (!check_if_active.isEmpty() && (!check_if_active) || isActive(true))) |
---|
[2318] | 22 | { |
---|
[2329] | 23 | if ( CXios::checkSumSend ) |
---|
[2318] | 24 | { |
---|
| 25 | const double* array = _data.dataFirst(); |
---|
| 26 | int numElements( _data.numElements() ); |
---|
| 27 | checkSumLike( array, numElements, true ); |
---|
| 28 | } |
---|
[1930] | 29 | modelToClientSourceFilter_->streamData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data); |
---|
[2318] | 30 | } |
---|
[1201] | 31 | } |
---|
[1021] | 32 | else if (instantDataFilter) |
---|
[640] | 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."); |
---|
[459] | 35 | } |
---|
[1622] | 36 | CATCH_DUMP_ATTR |
---|
[2318] | 37 | |
---|
[459] | 38 | |
---|
[593] | 39 | template <int N> |
---|
| 40 | void CField::getData(CArray<double, N>& _data) const |
---|
[1622] | 41 | TRY |
---|
[593] | 42 | { |
---|
[1930] | 43 | if (clientToModelStoreFilter_) |
---|
[593] | 44 | { |
---|
[1930] | 45 | CDataPacket::StatusCode status = clientToModelStoreFilter_->getData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data); |
---|
[2329] | 46 | if ( CXios::checkSumRecv ) |
---|
[2318] | 47 | { |
---|
| 48 | const double* array = _data.dataFirst(); |
---|
| 49 | int numElements( _data.numElements() ); |
---|
| 50 | checkSumLike( array, numElements, false ); |
---|
| 51 | } |
---|
[640] | 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."); |
---|
[593] | 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 | } |
---|
[1622] | 63 | CATCH |
---|
[2318] | 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 | |
---|
[352] | 132 | } // namespace xios |
---|
| 133 | |
---|
| 134 | #endif |
---|