Multiscale Universal Interface  2.0
A Concurrent Framework for Coupling Heterogeneous Solvers
algo_fixed_relaxation.h
Go to the documentation of this file.
1 /*****************************************************************************
2 * Multiscale Universal Interface Code Coupling Library *
3 * *
4 * Copyright (C) 2019 Y. H. Tang, S. Kudo, X. Bian, Z. Li, G. E. Karniadakis *
5 * W. Liu *
6 * *
7 * This software is jointly licensed under the Apache License, Version 2.0 *
8 * and the GNU General Public License version 3, you may use it according *
9 * to either. *
10 * *
11 * ** Apache License, version 2.0 ** *
12 * *
13 * Licensed under the Apache License, Version 2.0 (the "License"); *
14 * you may not use this file except in compliance with the License. *
15 * You may obtain a copy of the License at *
16 * *
17 * http://www.apache.org/licenses/LICENSE-2.0 *
18 * *
19 * Unless required by applicable law or agreed to in writing, software *
20 * distributed under the License is distributed on an "AS IS" BASIS, *
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
22 * See the License for the specific language governing permissions and *
23 * limitations under the License. *
24 * *
25 * ** GNU General Public License, version 3 ** *
26 * *
27 * This program is free software: you can redistribute it and/or modify *
28 * it under the terms of the GNU General Public License as published by *
29 * the Free Software Foundation, either version 3 of the License, or *
30 * (at your option) any later version. *
31 * *
32 * This program is distributed in the hope that it will be useful, *
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
35 * GNU General Public License for more details. *
36 * *
37 * You should have received a copy of the GNU General Public License *
38 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
39 *****************************************************************************/
40 
48 #ifndef MUI_COUPLING_ALGORITHM_FIXED_RELAXATION_H_
49 #define MUI_COUPLING_ALGORITHM_FIXED_RELAXATION_H_
50 
51 #include "../../general/util.h"
52 #include "../../config.h"
53 #include <iterator>
54 
55 namespace mui {
56 
57 template<typename CONFIG=default_config> class algo_fixed_relaxation {
58 public:
59  using REAL = typename CONFIG::REAL;
60  using INT = typename CONFIG::INT;
61  using time_type = typename CONFIG::time_type;
62  using iterator_type = typename CONFIG::iterator_type;
63  using point_type = typename CONFIG::point_type;
64 
65  algo_fixed_relaxation( REAL under_relaxation_factor = 1.0,
66  std::vector<std::pair<point_type, REAL>> pts_value_init =
67  std::vector<std::pair<point_type, REAL>>() ):
68  init_under_relaxation_factor_(under_relaxation_factor) {
69 
72 
73  if (!pts_value_init.empty()) {
74  pts_time_value_.insert(pts_time_value_.begin(),
75  std::make_pair(
76  std::make_pair(
77  std::numeric_limits<time_type>::lowest(),
79  ),pts_value_init
80  )
81  );
82  }
83  }
84 
85  //- relaxation based on single time value
86  template<typename OTYPE>
87  OTYPE relaxation(std::pair<time_type, iterator_type> t, point_type focus, OTYPE filtered_value) const {
88 
89  OTYPE filtered_old_value = 0.0;
90 
91  if (pts_time_value_.empty()) {
92 
93  filtered_old_value = 0.0;
94 
95  std::vector<std::pair<point_type, REAL>> pts_value_temp{
96  std::make_pair(focus,calculate_relaxed_value(filtered_value,filtered_old_value))
97  };
98 
99  pts_time_value_.insert(pts_time_value_.begin(),std::make_pair(t,pts_value_temp));
100 
101  return calculate_relaxed_value(filtered_value,filtered_old_value);
102 
103  } else { // pts_time_value_ not empty
104 
105  auto present_iter = std::find_if(pts_time_value_.begin(), pts_time_value_.end(),
106  [t](std::pair<std::pair<time_type,iterator_type>,std::vector<std::pair<point_type, REAL>>> b) {
107  return (((t.first - b.first.first) < std::numeric_limits<time_type>::epsilon()) &&
108  (t.second == b.first.second));
109  });
110 
111  auto mi=minimum_iterator_;
112  auto previous_iter = std::find_if(pts_time_value_.begin(), pts_time_value_.end(),
113  [t, &mi](std::pair<std::pair<time_type,iterator_type>,std::vector<std::pair<point_type, REAL>>> b) {
114  return ((t.second == mi) ?
115  (b.first.first < t.first) ||
116  (((t.first - b.first.first) < std::numeric_limits<time_type>::epsilon()) &&
117  (b.first.second == (mi - 1))) :
118  ((t.first - b.first.first) < std::numeric_limits<time_type>::epsilon()) &&
119  (b.first.second < t.second));
120  });
121 
122  if ((present_iter == std::end(pts_time_value_)) &&
123  (previous_iter == std::end(pts_time_value_)) ) {
124 
125  std::cerr << "Non-monotonic time marching does not (yet) supported for the Fixed Relaxation coupling method! " << std::endl;
126 
127  } else if ((present_iter != std::end(pts_time_value_)) &&
128  (previous_iter == std::end(pts_time_value_)) ) {
129 
130  auto pts_relx_val_iter = std::find_if(present_iter->second.begin(),
131  present_iter->second.end(), [focus](std::pair<point_type, REAL> b) {
132  return normsq(focus - b.first) < std::numeric_limits<REAL>::epsilon();
133  });
134 
135  if ( pts_relx_val_iter == std::end(present_iter->second) ) {
136 
137  // Interpolate the relaxed value by N2_linear
138  REAL r2min_1st = std::numeric_limits<REAL>::max();
139  REAL r2min_2nd = std::numeric_limits<REAL>::max();
140  OTYPE value_1st = 0, value_2nd = 0;
141  for( size_t i = 0 ; i < present_iter->second.size() ; i++ ) {
142  REAL dr2 = normsq( focus - present_iter->second[i].first );
143  if ( dr2 < r2min_1st ) {
144  r2min_2nd = r2min_1st;
145  value_2nd = value_1st;
146  r2min_1st = dr2;
147  value_1st = present_iter->second[i].second ;
148  } else if ( dr2 < r2min_2nd ) {
149  r2min_2nd = dr2;
150  value_2nd = present_iter->second[i].second ;
151  }
152  }
153 
154  REAL r1 = std::sqrt( r2min_1st );
155  REAL r2 = std::sqrt( r2min_2nd );
156 
157  auto relaxed_value_temp = ( value_1st * r2 + value_2nd * r1 ) / ( r1 + r2 );
158 
159  present_iter->second.insert(present_iter->second.begin(),std::make_pair(focus, relaxed_value_temp));
160 
161  return relaxed_value_temp;
162 
163  } else {
164 
165  return pts_relx_val_iter->second;
166 
167  }
168 
169  } else if ((present_iter == std::end(pts_time_value_)) &&
170  (previous_iter != std::end(pts_time_value_)) ) {
171 
172  auto pts_relx_val_iter = std::find_if(previous_iter->second.begin(),
173  previous_iter->second.end(), [focus](std::pair<point_type, REAL> b) {
174  return normsq(focus - b.first) < std::numeric_limits<REAL>::epsilon();
175  });
176 
177  if ( pts_relx_val_iter == std::end(previous_iter->second) ) {
178 
179  // Interpolate the relaxed value by N2_linear
180  REAL r2min_1st = std::numeric_limits<REAL>::max();
181  REAL r2min_2nd = std::numeric_limits<REAL>::max();
182  OTYPE value_1st = 0, value_2nd = 0;
183  for( size_t i = 0 ; i < previous_iter->second.size() ; i++ ) {
184  REAL dr2 = normsq( focus - previous_iter->second[i].first );
185  if ( dr2 < r2min_1st ) {
186  r2min_2nd = r2min_1st;
187  value_2nd = value_1st;
188  r2min_1st = dr2;
189  value_1st = previous_iter->second[i].second ;
190  } else if ( dr2 < r2min_2nd ) {
191  r2min_2nd = dr2;
192  value_2nd = previous_iter->second[i].second ;
193  }
194  }
195 
196  REAL r1 = std::sqrt( r2min_1st );
197  REAL r2 = std::sqrt( r2min_2nd );
198 
199  filtered_old_value = ( value_1st * r2 + value_2nd * r1 ) / ( r1 + r2 );
200 
201  } else {
202 
203  filtered_old_value = pts_relx_val_iter->second;
204 
205  }
206 
207  std::vector<std::pair<point_type, REAL>> pts_value_temp{
208  std::make_pair(focus,calculate_relaxed_value(filtered_value,filtered_old_value))
209  };
210 
211  pts_time_value_.insert(pts_time_value_.begin(),std::make_pair(t, pts_value_temp));
212 
213  return calculate_relaxed_value(filtered_value,filtered_old_value);
214 
215  } else {
216 
217  auto pts_relx_val_iter = std::find_if(previous_iter->second.begin(),
218  previous_iter->second.end(), [focus](std::pair<point_type, REAL> b) {
219  return normsq(focus - b.first) < std::numeric_limits<REAL>::epsilon();
220  });
221 
222  if ( pts_relx_val_iter == std::end(previous_iter->second) ) {
223 
224  // Interpolate the relaxed value by N2_linear
225  REAL r2min_1st = std::numeric_limits<REAL>::max();
226  REAL r2min_2nd = std::numeric_limits<REAL>::max();
227  OTYPE value_1st = 0, value_2nd = 0;
228  for( size_t i = 0 ; i < previous_iter->second.size() ; i++ ) {
229  REAL dr2 = normsq( focus - previous_iter->second[i].first );
230  if ( dr2 < r2min_1st ) {
231  r2min_2nd = r2min_1st;
232  value_2nd = value_1st;
233  r2min_1st = dr2;
234  value_1st = previous_iter->second[i].second ;
235  } else if ( dr2 < r2min_2nd ) {
236  r2min_2nd = dr2;
237  value_2nd = previous_iter->second[i].second ;
238  }
239  }
240 
241  REAL r1 = std::sqrt( r2min_1st );
242  REAL r2 = std::sqrt( r2min_2nd );
243 
244  filtered_old_value = ( value_1st * r2 + value_2nd * r1 ) / ( r1 + r2 );
245 
246  } else {
247 
248  filtered_old_value = pts_relx_val_iter->second;
249 
250  }
251 
252  auto pts_present_relx_val_iter = std::find_if(present_iter->second.begin(),
253  present_iter->second.end(), [focus](std::pair<point_type, REAL> b) {
254  return normsq(focus - b.first) < std::numeric_limits<REAL>::epsilon();
255  });
256 
257  if ( pts_present_relx_val_iter == std::end(present_iter->second) ) {
258 
259  present_iter->second.insert(present_iter->second.begin(),
260  std::make_pair(focus,calculate_relaxed_value(
261  filtered_value,filtered_old_value)
262  )
263  );
264 
265  } else {
266 
267  pts_present_relx_val_iter->second = calculate_relaxed_value(filtered_value,filtered_old_value);
268 
269  }
270 
271  return calculate_relaxed_value(filtered_value,filtered_old_value);
272 
273  }
274  return calculate_relaxed_value(filtered_value,filtered_old_value);
275  }
276  }
277 
278 private:
279  template<typename OTYPE>
280  OTYPE calculate_relaxed_value(OTYPE filtered_value, OTYPE filtered_old_value) const {
281 
282  return (under_relaxation_factor_ * filtered_value) + ((1 - under_relaxation_factor_) * filtered_old_value);
283 
284  }
285 
286 protected:
290 
291  mutable std::vector<std::pair<std::pair<time_type,iterator_type>,std::vector<std::pair<point_type, REAL>>>> pts_time_value_;
292 
293 };
294 
295 }
296 
297 #endif /* MUI_COUPLING_ALGORITHM_FIXED_RELAXATION_H_ */
Definition: algo_fixed_relaxation.h:57
typename CONFIG::point_type point_type
Definition: algo_fixed_relaxation.h:63
std::vector< std::pair< std::pair< time_type, iterator_type >, std::vector< std::pair< point_type, REAL > > > > pts_time_value_
Definition: algo_fixed_relaxation.h:291
typename CONFIG::REAL REAL
Definition: algo_fixed_relaxation.h:59
REAL init_under_relaxation_factor_
Definition: algo_fixed_relaxation.h:287
typename CONFIG::iterator_type iterator_type
Definition: algo_fixed_relaxation.h:62
typename CONFIG::time_type time_type
Definition: algo_fixed_relaxation.h:61
typename CONFIG::INT INT
Definition: algo_fixed_relaxation.h:60
algo_fixed_relaxation(REAL under_relaxation_factor=1.0, std::vector< std::pair< point_type, REAL >> pts_value_init=std::vector< std::pair< point_type, REAL >>())
Definition: algo_fixed_relaxation.h:65
OTYPE relaxation(std::pair< time_type, iterator_type > t, point_type focus, OTYPE filtered_value) const
Definition: algo_fixed_relaxation.h:87
REAL under_relaxation_factor_
Definition: algo_fixed_relaxation.h:288
iterator_type minimum_iterator_
Definition: algo_fixed_relaxation.h:289
Definition: comm.h:54
SCALAR max(vexpr< E, SCALAR, D > const &u)
Definition: point.h:350
SCALAR normsq(vexpr< E, SCALAR, D > const &u)
Definition: point.h:380