tasks.cc 34 KB
Newer Older
1
2
3
4
5
6
#include <iostream>
#include <numeric>
#include <string>
#include <functional>
#include "readers.hh"
#include "CanopyHydrology_cc.hh"
7
#include "CanopyHydrology_SnowWater_impl.hh"
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "legion.h"
#include "tasks.hh"

using namespace Legion;

//
// SumMinMaxReduction task
//
// =============================================================================

Future
SumMinMaxReduction::launch(Context ctx, Runtime *runtime,
                           Data<2>& domain, const std::string& fname)
{
  TaskLauncher accumlate_launcher(taskid, TaskArgument());
  accumlate_launcher.add_region_requirement(
      RegionRequirement(domain.logical_region, READ_ONLY, EXCLUSIVE,
                        domain.logical_region));
  accumlate_launcher.add_field(0, domain.field_ids[fname]);
  return runtime->execute_task(ctx, accumlate_launcher);
}

std::array<double,3>
SumMinMaxReduction::cpu_execute_task(const Task *task,
                         const std::vector<PhysicalRegion> &regions,
                         Context ctx, Runtime *runtime)
{
  assert(regions.size() == 1);
  assert(task->regions.size() == 1);
  assert(task->regions[0].privilege_fields.size() == 1);
38
  //std::cout << "LOG: Executing SumMinMax Task" << std::endl;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  FieldID fid = *(task->regions[0].privilege_fields.begin());

  FieldAccessor<READ_ONLY,double,2,coord_t,
                Realm::AffineAccessor<double,2,coord_t> > field(regions[0], fid);
  Rect<2> rect = runtime->get_index_space_domain(ctx,
          task->regions[0].region.get_index_space());

  std::array<double,3> sum_min_max = {0., 0., 0.};
  for (PointInRectIterator<2> pir(rect); pir(); pir++) {  
    auto val = field[*pir];
    sum_min_max[0] += val;
    sum_min_max[1] = std::min(sum_min_max[1], val);
    sum_min_max[2] = std::max(sum_min_max[2], val);
  }
  return sum_min_max;
}

void
SumMinMaxReduction::preregister(TaskID new_taskid) {
  // taskid = (taskid == AUTO_GENERATE_ID ?
  //           Legion::Runtime::generate_static_task_id() :
  //             new_taskid);
            
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<std::array<double,3>,cpu_execute_task>(registrar, name.c_str());
}    

TaskID SumMinMaxReduction::taskid = TaskIDs::UTIL_SUM_MIN_MAX_REDUCTION;
std::string SumMinMaxReduction::name = "sum_min_max_reduction";



73
//
74
// SumMinMaxReduction1D task
75
76
77
78
//
// =============================================================================

Future
79
SumMinMaxReduction1D::launch(Context ctx, Runtime *runtime,
80
81
                           Data<1>& domain, const std::string& fname)
{
82
83
  TaskLauncher accumlate1D_launcher(taskid, TaskArgument());
  accumlate1D_launcher.add_region_requirement(
84
85
      RegionRequirement(domain.logical_region, READ_ONLY, EXCLUSIVE,
                        domain.logical_region));
86
87
  accumlate1D_launcher.add_field(0, domain.field_ids[fname]);
  return runtime->execute_task(ctx, accumlate1D_launcher);
88
89
90
}

std::array<double,3>
91
SumMinMaxReduction1D::cpu_execute_task(const Task *task,
92
93
94
95
96
97
98
99
100
101
102
103
104
105
                         const std::vector<PhysicalRegion> &regions,
                         Context ctx, Runtime *runtime)
{
  assert(regions.size() == 1);
  assert(task->regions.size() == 1);
  assert(task->regions[0].privilege_fields.size() == 1);
  //std::cout << "LOG: Executing SumMinMax Task" << std::endl;
  FieldID fid = *(task->regions[0].privilege_fields.begin());

  FieldAccessor<READ_ONLY,double,2,coord_t,
                Realm::AffineAccessor<double,2,coord_t> > field(regions[0], fid);
  Rect<2> rect = runtime->get_index_space_domain(ctx,
          task->regions[0].region.get_index_space());

106
  std::array<double,3> sum_min_max1D = {0., 0., 0.};
107
  for (PointInRectIterator<2> pir(rect); pir(); pir++) {  
108
109
110
111
    auto val1D = field[*pir];
    sum_min_max1D[0] += val1D;
    sum_min_max1D[1] = std::min(sum_min_max1D[1], val1D);
    sum_min_max1D[2] = std::max(sum_min_max1D[2], val1D);
112
  }
113
  return sum_min_max1D;
114
115
116
}

void
117
SumMinMaxReduction1D::preregister(TaskID new_taskid) {
118
119
120
121
122
123
124
125
126
127
  // taskid = (taskid == AUTO_GENERATE_ID ?
  //           Legion::Runtime::generate_static_task_id() :
  //             new_taskid);
            
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<std::array<double,3>,cpu_execute_task>(registrar, name.c_str());
}    

128
129
TaskID SumMinMaxReduction1D::taskid = TaskIDs::UTIL_SUM_MIN_MAX_REDUCTION1D;
std::string SumMinMaxReduction1D::name = "sum_min_max_reduction1D";
130
131


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//
// InitPhenology task
//
// =============================================================================
Future
InitPhenology::launch(Context ctx, Runtime *runtime, Data<2>& data)
{
  TaskLauncher phenology_launcher(taskid, TaskArgument(NULL, 0));
  phenology_launcher.add_region_requirement(
      RegionRequirement(data.logical_region, WRITE_DISCARD, EXCLUSIVE,
                        data.logical_region));

  phenology_launcher.add_field(0, data.field_ids["elai"]);
  phenology_launcher.add_field(0, data.field_ids["esai"]);
  return runtime->execute_task(ctx, phenology_launcher);
}

void
InitPhenology::cpu_execute_task(const Task *task,
                   const std::vector<PhysicalRegion> &regions,
                   Context ctx, Runtime *runtime)
{
  assert(regions.size() == 1);
  assert(task->regions.size() == 1);
  assert(task->regions[0].instance_fields.size() == 2); // LAI, SAI

158
  //std::cout << "LOG: Executing InitPhenology task" << std::endl;
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  const FieldAccessor<WRITE_DISCARD,double,2> elai(regions[0],
          task->regions[0].instance_fields[0]);
  const FieldAccessor<WRITE_DISCARD,double,2> esai(regions[0],
          task->regions[0].instance_fields[1]);

  Rect<2> my_bounds = Domain(runtime->get_index_space_domain(
      regions[0].get_logical_region().get_index_space()));
  coord_t n_grid_cells = my_bounds.hi[0] - my_bounds.lo[0] + 1;
  coord_t n_pfts = my_bounds.hi[1] - my_bounds.lo[1] + 1;
  
  assert(n_grid_cells == 24); // hard coded as two reads of 2x 12 increments
  ELM::Utils::read_phenology("../links/surfacedataWBW.nc", 12, n_pfts, 0, elai, esai);
  ELM::Utils::read_phenology("../links/surfacedataBRW.nc", 12, n_pfts, 12, elai, esai);
}

void
InitPhenology::preregister(TaskID new_taskid)
{
  // taskid = (taskid == AUTO_GENERATE_ID ?
  //           Legion::Runtime::generate_static_task_id() :
  //             new_taskid);
            
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<cpu_execute_task>(registrar, name.c_str());
}    

TaskID InitPhenology::taskid = TaskIDs::INIT_PHENOLOGY;
std::string InitPhenology::name = "init_phenology";



//
// InitForcing task
//
// =============================================================================
Future
InitForcing::launch(Context ctx, Runtime *runtime, Data<2>& data)
{

200
  //std::cout << "LOG: Launching Init Forcing" << std::endl;
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  
  TaskLauncher forcing_launcher(taskid, TaskArgument(NULL, 0));
  forcing_launcher.add_region_requirement(
      RegionRequirement(data.logical_region, WRITE_DISCARD, EXCLUSIVE,
                        data.logical_region));

  forcing_launcher.add_field(0, data.field_ids["forc_rain"]);
  forcing_launcher.add_field(0, data.field_ids["forc_snow"]);
  forcing_launcher.add_field(0, data.field_ids["forc_air_temp"]);
  forcing_launcher.add_field(0, data.field_ids["forc_irrig"]);
  return runtime->execute_task(ctx, forcing_launcher);
}

int
InitForcing::cpu_execute_task(const Task *task,
                   const std::vector<PhysicalRegion> &regions,
                   Context ctx, Runtime *runtime)
{
  assert(regions.size() == 1);
  assert(task->regions.size() == 1);
  assert(task->regions[0].instance_fields.size() == 4);

223
  //std::cout << "LOG: Executing InitForcing task" << std::endl;
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  Rect<2> my_bounds = Domain(runtime->get_index_space_domain(
      regions[0].get_logical_region().get_index_space()));
  coord_t n_times_max = my_bounds.hi[0] - my_bounds.lo[0] + 1;
  coord_t n_grid_cells = my_bounds.hi[1] - my_bounds.lo[1] + 1;
  
  // init rain, snow, and air temp through reader
  const FieldAccessor<WRITE_DISCARD,double,2> rain(regions[0],
          task->regions[0].instance_fields[0]);
  const FieldAccessor<WRITE_DISCARD,double,2> snow(regions[0],
          task->regions[0].instance_fields[1]);
  const FieldAccessor<WRITE_DISCARD,double,2> air_temp(regions[0],
          task->regions[0].instance_fields[2]);
  const FieldAccessor<WRITE_DISCARD,double,2> irrig(regions[0],
          task->regions[0].instance_fields[3]);
  int n_times = ELM::Utils::read_forcing("../links/forcing",
          n_times_max, 0, n_grid_cells,
          rain, snow, air_temp);

  // init irrig to zero
  for (size_t t=0; t!=n_times_max; ++t) {
    for (size_t g=0; g!=n_grid_cells; ++g) {
      irrig[t][g] = 0.;
    }
  }
  return n_times;
}  

void
InitForcing::preregister(TaskID new_taskid)
{
  // taskid = (taskid == AUTO_GENERATE_ID ?
  //           Legion::Runtime::generate_static_task_id() :
  //             new_taskid);
            
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<int,cpu_execute_task>(registrar, name.c_str());
}    

TaskID InitForcing::taskid = TaskIDs::INIT_FORCING;
std::string InitForcing::name = "init_forcing";






//
// CanopyHydrology Interception task manager
//
// =============================================================================

FutureMap
CanopyHydrology_Interception::launch(Context ctx, Runtime *runtime,
        Rect<1>& color_space,
        Data<2>& phenology,
        Data<2>& forcing,
        Data<2>& flux,
        int itime)
{
  // launch task to call interception
  // -- fixed magic parameters as arguments
  const int ctype = 1;
  const int ltype = 1;
  const bool urbpoi = false;
  const bool do_capsnow = false;
  const int frac_veg_nosno = 1;
  const double dewmx = 0.1;
  const double dtime = 1800.0;

  auto args = std::make_tuple(itime, dtime, ltype, ctype, urbpoi,
          do_capsnow, dewmx, frac_veg_nosno);
  ArgumentMap arg_map;
298
  IndexLauncher launcher(taskid,
299
300
301
          color_space, TaskArgument(&args, sizeof(args)), arg_map);

  // -- permissions on forcing
302
  launcher.add_region_requirement(
303
304
      RegionRequirement(forcing.logical_partition, forcing.projection_id,
                        READ_ONLY, EXCLUSIVE, forcing.logical_region));
305
306
307
  launcher.add_field(0, forcing.field_ids["forc_rain"]);
  launcher.add_field(0, forcing.field_ids["forc_snow"]);
  launcher.add_field(0, forcing.field_ids["forc_irrig"]);
308
309

  // -- permissions on phenology
310
  launcher.add_region_requirement(
311
312
      RegionRequirement(phenology.logical_partition, phenology.projection_id,
                        READ_ONLY, EXCLUSIVE, phenology.logical_region));
313
314
  launcher.add_field(1, phenology.field_ids["elai"]);
  launcher.add_field(1, phenology.field_ids["esai"]);
315
316
  
  // -- permissions on output
317
  launcher.add_region_requirement(
318
319
320
321
322
323
324
      RegionRequirement(flux.logical_partition, flux.projection_id,
                        READ_WRITE, EXCLUSIVE, flux.logical_region));
  std::vector<std::string> output{"qflx_prec_intr", "qflx_irrig",
                                  "qflx_prec_grnd", "qflx_snwcp_liq",
                                  "qflx_snwcp_ice", "qflx_snow_grnd_patch",
                                  "qflx_rain_grnd","h2ocan"};
  for (auto fname : output)
325
    launcher.add_field(2,flux.field_ids[fname]);
326
327

  // -- launch the interception
328
  return runtime->execute_index_space(ctx, launcher);
329
330
331
332
333
334
335
336
337
338
}

void
CanopyHydrology_Interception::cpu_execute_task(const Task *task,
                 const std::vector<PhysicalRegion> &regions,
                 Context ctx, Runtime *runtime)
{
  assert(regions.size() == 3);
  assert(regions.size() == 3);
  assert(task->regions[0].instance_fields.size() == 3);
339
  //std::cout << "LOG: Executing Interception task" << std::endl;
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

  // process args / parameters
  int lcv_time;
  double dtime, dewmx;
  int ltype, ctype, frac_veg_nosno;
  bool urbpoi, do_capsnow;
  using args_t = std::tuple<int, double, int, int, bool, bool, double, int>;
  std::tie(lcv_time, dtime, ltype, ctype, urbpoi, do_capsnow, dewmx, frac_veg_nosno) =
      *((args_t*) task->args);

  // get accessors
  using AffineAccessorRO = FieldAccessor<READ_ONLY,double,2,coord_t,
                                         Realm::AffineAccessor<double,2,coord_t> >;
  using AffineAccessorRW = FieldAccessor<READ_WRITE,double,2,coord_t,
                                         Realm::AffineAccessor<double,2,coord_t> >;
  
  // -- forcing
357
358
359
360
  // //std::cout << "rain, snow, irrig = "
  //           << task->regions[0].instance_fields[0] << ","
  //           << task->regions[0].instance_fields[1] << ","
  //           << task->regions[0].instance_fields[2] << std::endl;
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  const AffineAccessorRO forc_rain(regions[0], task->regions[0].instance_fields[0]);
  const AffineAccessorRO forc_snow(regions[0], task->regions[0].instance_fields[1]);
  const AffineAccessorRO forc_irrig(regions[0], task->regions[0].instance_fields[2]);

  // -- phenology
  const AffineAccessorRO elai(regions[1], task->regions[1].instance_fields[0]);
  const AffineAccessorRO esai(regions[1], task->regions[1].instance_fields[1]);

  // -- output
  const AffineAccessorRW qflx_prec_intr(regions[2], task->regions[2].instance_fields[0]);
  const AffineAccessorRW qflx_irrig(regions[2], task->regions[2].instance_fields[1]);
  const AffineAccessorRW qflx_prec_grnd(regions[2], task->regions[2].instance_fields[2]);
  const AffineAccessorRW qflx_snwcp_liq(regions[2], task->regions[2].instance_fields[3]);
 
  const AffineAccessorRW qflx_snwcp_ice(regions[2], task->regions[2].instance_fields[4]);
  const AffineAccessorRW qflx_snow_grnd_patch(regions[2], task->regions[2].instance_fields[5]); 
  const AffineAccessorRW qflx_rain_grnd(regions[2], task->regions[2].instance_fields[6]);
  const AffineAccessorRW h2ocan(regions[2], task->regions[2].instance_fields[7]);

  LogicalRegion lr = regions[2].get_logical_region();
  IndexSpaceT<2> is(lr.get_index_space());
  Rect<2> bounds = Domain(runtime->get_index_space_domain(is));

384
  //std::cout << "LOG: With bounds: " << bounds.lo << "," << bounds.hi << std::endl;
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
  
  int n_irrig_steps_left = 0.;  // NOTE: still not physical quite sure what to do with this one.
  
  for (size_t g = bounds.lo[0]; g != bounds.hi[0]+1; ++g) {
    for (size_t p = bounds.lo[1]; p != bounds.hi[1]+1; ++p) {
      ELM::CanopyHydrology_Interception(dtime,
              forc_rain[lcv_time][g], forc_snow[lcv_time][g], forc_irrig[lcv_time][g],
              ltype, ctype, urbpoi, do_capsnow,
              elai[g][p], esai[g][p], dewmx, frac_veg_nosno,
              h2ocan[g][p], n_irrig_steps_left,
              qflx_prec_intr[g][p], qflx_irrig[g][p], qflx_prec_grnd[g][p],
              qflx_snwcp_liq[g][p], qflx_snwcp_ice[g][p],
              qflx_snow_grnd_patch[g][p], qflx_rain_grnd[g][p]);
    }
  }
}


void
CanopyHydrology_Interception::preregister(TaskID new_taskid)
{
  // taskid = (taskid == AUTO_GENERATE_ID ?
  //           Legion::Runtime::generate_static_task_id() :
  //             new_taskid);
            
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<cpu_execute_task>(registrar, name.c_str());
}    

TaskID CanopyHydrology_Interception::taskid = TaskIDs::CANOPY_HYDROLOGY_INTERCEPTION;
std::string CanopyHydrology_Interception::name = "canopy_hydrology_interception";





//
// CanopyHydrology FracWet task manager
//
// =============================================================================

FutureMap
CanopyHydrology_FracWet::launch(Context ctx, Runtime *runtime,
        Rect<1>& color_space,
        Data<2>& phenology,
        Data<2>& flux)
{
  const int frac_veg_nosno = 1;
  const double dewmx = 0.1;
  double fwet = 0., fdry = 0.;
  auto args = std::make_tuple(dewmx, frac_veg_nosno, fwet, fdry);
  ArgumentMap arg_map;
439
  IndexLauncher launcher(taskid,
440
441
442
          color_space, TaskArgument(&args, sizeof(args)), arg_map);

  // -- permissions on phenology
443
  launcher.add_region_requirement(
444
445
      RegionRequirement(phenology.logical_partition, phenology.projection_id,
                        READ_ONLY, EXCLUSIVE, phenology.logical_region));
446
447
  launcher.add_field(0, phenology.field_ids["elai"]);
  launcher.add_field(0, phenology.field_ids["esai"]);
448
449
  
  // -- permissions on output
450
  launcher.add_region_requirement(
451
452
453
454
      RegionRequirement(flux.logical_partition, flux.projection_id,
                        READ_WRITE, EXCLUSIVE, flux.logical_region));
  std::vector<std::string> output{"h2ocan"};
  for (auto fname : output)
455
    launcher.add_field(1,flux.field_ids[fname]);
456
457

  // -- launch the interception
458
  return runtime->execute_index_space(ctx, launcher);
459
460
461
462
463
464
465
466
467
468
}

void
CanopyHydrology_FracWet::cpu_execute_task(const Task *task,
                 const std::vector<PhysicalRegion> &regions,
                 Context ctx, Runtime *runtime)
{
  assert(regions.size() == 2);
  assert(regions.size() == 2);
  assert(task->regions[0].instance_fields.size() == 2);
469
  //std::cout << "LOG: Executing FracWet task" << std::endl;
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484

  // process args / parameters
  double dewmx, fwet, fdry;
  int frac_veg_nosno;
  using args_t = std::tuple<double, int, double, double>;
  std::tie(dewmx, frac_veg_nosno, fwet, fdry) =
      *((args_t*) task->args);

  // get accessors
  using AffineAccessorRO = FieldAccessor<READ_ONLY,double,2,coord_t,
                                         Realm::AffineAccessor<double,2,coord_t> >;
  using AffineAccessorRW = FieldAccessor<READ_WRITE,double,2,coord_t,
                                         Realm::AffineAccessor<double,2,coord_t> >;
  
  // -- phenology
485
486
487
  // //std::cout << "elai,esai = "
  //           << task->regions[0].instance_fields[0] << ","
  //           << task->regions[0].instance_fields[1] <<  std::endl;
488
489
  
  const AffineAccessorRO elai(regions[0], task->regions[0].instance_fields[0]);
490
  const AffineAccessorRO esai(regions[0], task->regions[0].instance_fields[1]);
491
492
493
494

  // -- output
  const AffineAccessorRW h2ocan(regions[1], task->regions[1].instance_fields[0]);

495
  LogicalRegion lr = regions[0].get_logical_region();
496
497
498
  IndexSpaceT<2> is(lr.get_index_space());
  Rect<2> bounds = Domain(runtime->get_index_space_domain(is));

499
  //std::cout << "LOG: With bounds: " << bounds.lo << "," << bounds.hi << std::endl;
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
    
  for (size_t g = bounds.lo[0]; g != bounds.hi[0]+1; ++g) {
    for (size_t p = bounds.lo[1]; p != bounds.hi[1]+1; ++p) {
      ELM::CanopyHydrology_FracWet(frac_veg_nosno,
              h2ocan[g][p], elai[g][p], esai[g][p], dewmx, fwet, fdry);
    }
  }
}


void
CanopyHydrology_FracWet::preregister(TaskID new_taskid)
{
              
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<cpu_execute_task>(registrar, name.c_str());
}    

TaskID CanopyHydrology_FracWet::taskid = TaskIDs::CANOPY_HYDROLOGY_FRACWET;
std::string CanopyHydrology_FracWet::name = "canopy_hydrology_fracwet";





//
// Sum Over PFTS task manager
//
// =============================================================================

FutureMap
SumOverPFTs::launch(Context ctx, Runtime *runtime,
        Rect<1>& color_space,
        Data<2>& flux,
        Data<1>& surface)
{
  auto args = std::make_tuple(NULL);
  ArgumentMap arg_map;
540
  IndexLauncher launcher(taskid,
541
542
543
          color_space, TaskArgument(&args, sizeof(args)), arg_map);

   
544
  // -- permissions on input
545
  launcher.add_region_requirement(
546
      RegionRequirement(flux.logical_partition, flux.projection_id,
547
548
549
                        READ_ONLY, EXCLUSIVE, flux.logical_region));
  std::vector<std::string> input{"qflx_snow_grnd_patch"};
  for (auto fname : input)
550
    launcher.add_field(0,flux.field_ids[fname]);
551
552

  // -- permissions on output
553
  launcher.add_region_requirement(
554
      RegionRequirement(surface.logical_partition, surface.projection_id,
555
                        WRITE_DISCARD, EXCLUSIVE, surface.logical_region));
556
557
  std::vector<std::string> output1{"qflx_snow_grnd_col"};
  for (auto fname1 : output1)
558
    launcher.add_field(1,surface.field_ids[fname1]);
559
560

  // -- launch the interception
561
  return runtime->execute_index_space(ctx, launcher);
562
563
564
565
566
567
568
569
}

void
SumOverPFTs::cpu_execute_task(const Task *task,
                 const std::vector<PhysicalRegion> &regions,
                 Context ctx, Runtime *runtime)
{
  assert(regions.size() == 2);
570
571
  assert(task->regions[0].instance_fields.size() == 1);
  assert(task->regions[1].instance_fields.size() == 1);
572
  //std::cout << "LOG: Executing SumOverPFTs task" << std::endl;
573
574
575
576

 // get accessors
  using AffineAccessorRO = FieldAccessor<READ_ONLY,double,2,coord_t,
                                         Realm::AffineAccessor<double,2,coord_t> >;
577
578
579
580
  using AffineAccessorWO = FieldAccessor<WRITE_DISCARD,double,1,coord_t,
                                         Realm::AffineAccessor<double,1,coord_t> >;
 // -- input
  const AffineAccessorRO qflx_snow_grnd_patch (regions[0], task->regions[0].instance_fields[0]);
581
  // -- output
582
583
  const AffineAccessorWO qflx_snow_grnd_col(regions[1], task->regions[1].instance_fields[0]);
  
584
585
586
587
588
589
  
  
  LogicalRegion lr = regions[0].get_logical_region();
  IndexSpaceT<2> is(lr.get_index_space());
  Rect<2> bounds = Domain(runtime->get_index_space_domain(is));

590
  //std::cout << "LOG: With bounds: " << bounds.lo << "," << bounds.hi << std::endl;
591
   
592
  for (int g = bounds.lo[0]; g != bounds.hi[0]+1; ++g) {
593
594
    double sum = 0 ;    
    for (int p = bounds.lo[1]; p != bounds.hi[1]+1; ++p) {
595
      sum += qflx_snow_grnd_patch[g][p];
596
597
    }
    qflx_snow_grnd_col[g] = sum ;
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
  }
}


void
SumOverPFTs::preregister(TaskID new_taskid)
{
             
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<cpu_execute_task>(registrar, name.c_str());
}    

TaskID SumOverPFTs::taskid = TaskIDs::SUM_OVER_PFTS;
std::string SumOverPFTs::name = "sum_over_pfts";





//
// CanopyHydrology SnowWater task manager
//
// =============================================================================

FutureMap
CanopyHydrology_SnowWater::launch(Context ctx, Runtime *runtime,
        Rect<1>& color_space,
        Data<2>& forcing,
        Data<2>& soil,
        Data<1>& surface,
        int itime)
{
  // launch task to call interception
  // -- fixed magic parameters as arguments
  const int ctype = 1;
  const int ltype = 1;
  const bool urbpoi = false;
  const bool do_capsnow = false;
  const int oldfflag = 0;
  const double dtime = 1800.0;
  const double qflx_snow_melt = 0.;
  double qflx_floodg = 0.0;
  const double n_melt = 0.7;

  auto args = std::make_tuple(itime,dtime, qflx_floodg,ltype, ctype, urbpoi, do_capsnow, oldfflag, qflx_snow_melt, n_melt); 
  ArgumentMap arg_map;
646
  IndexLauncher launcher(taskid,
647
648
649
          color_space, TaskArgument(&args, sizeof(args)), arg_map);

    // -- permissions on forcing
650
  launcher.add_region_requirement(
651
652
      RegionRequirement(forcing.logical_partition, forcing.projection_id,
                        READ_ONLY, EXCLUSIVE, forcing.logical_region));
653
  launcher.add_field(0, forcing.field_ids["forc_air_temp"]);
654
  
655
656
  // -- permissions on soil
  launcher.add_region_requirement(
657
658
659
660
661
      RegionRequirement(soil.logical_partition, soil.projection_id,
                        READ_WRITE, EXCLUSIVE, soil.logical_region));
  std::vector<std::string> output{"swe_old", "h2osoi_liq", "h2osoi_ice", "t_soisno", "frac_iceold",
                                  "dz", "z", "zi"};
  for (auto fname : output)
662
    launcher.add_field(1,soil.field_ids[fname]);
663

664
665
  // -- permissions on surface
  launcher.add_region_requirement(
666
667
668
669
670
671
      RegionRequirement(surface.logical_partition, surface.projection_id,
                        READ_WRITE, EXCLUSIVE, surface.logical_region));
  std::vector<std::string> output1{"t_grnd", "h2osno", "snow_depth", "integrated_snow",
     "qflx_snow_grnd_col", "qflx_snow_h2osfc",
     "qflx_floodc", "frac_snow_eff", "frac_sno", "frac_h2osfc", "snow_level"};
  for (auto fname1 : output1)
672
    launcher.add_field(2,surface.field_ids[fname1]);
673
674

  // -- launch the interception
675
  return runtime->execute_index_space(ctx, launcher);
676
677
678
679
680
681
682
683
}

void
CanopyHydrology_SnowWater::cpu_execute_task(const Task *task,
                 const std::vector<PhysicalRegion> &regions,
                 Context ctx, Runtime *runtime)
{
  assert(regions.size() == 3);
684
685
686
687
  assert(task->regions[0].instance_fields.size() == 1);
  assert(task->regions[1].instance_fields.size() == 8);
  assert(task->regions[2].instance_fields.size() == 11);

688
  //std::cout << "LOG: Executing SnowWater task" << std::endl;
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
  int lcv_time;
  double dtime, qflx_snow_melt , qflx_floodg , n_melt ;
  int ltype, ctype, oldfflag;
  bool urbpoi, do_capsnow;
  using args_t = std::tuple<int,double,double,int,int,bool,bool,int,double,double>;
  std::tie(lcv_time,dtime, qflx_floodg, ltype, ctype, urbpoi, do_capsnow, oldfflag, qflx_snow_melt, n_melt) =
      *((args_t*) task->args);

  // get accessors
  using AffineAccessorRO = FieldAccessor<READ_ONLY,double,2,coord_t,
                                         Realm::AffineAccessor<double,2,coord_t> >;
  using AffineAccessorRW = FieldAccessor<READ_WRITE,double,2,coord_t,
                                         Realm::AffineAccessor<double,2,coord_t> >;
  using AffineAccessorRO1 = FieldAccessor<READ_ONLY,double,1,coord_t,
                                         Realm::AffineAccessor<double,1,coord_t> >;
  using AffineAccessorRW1 = FieldAccessor<READ_WRITE,double,1,coord_t,
                                         Realm::AffineAccessor<double,1,coord_t> >;
706
707
  using AffineAccessorWO1 = FieldAccessor<WRITE_DISCARD,double,1,coord_t,
                                         Realm::AffineAccessor<double,1,coord_t> >;
708
709
710
711
712
  using AffineAccessorRW1_int = FieldAccessor<READ_WRITE,int,1,coord_t,
                                         Realm::AffineAccessor<int,1,coord_t> >;

  
  // -- forcing
713
714
  // //std::cout << "air_temp = "
  //           << task->regions[0].instance_fields[0] << std::endl;
715
716
  const AffineAccessorRO forc_air_temp(regions[0], task->regions[0].instance_fields[0]);
  
717
  // -- soil
718
719
720
721
722
723
724
725
726
727
  const AffineAccessorRW swe_old(regions[1], task->regions[1].instance_fields[0]);
  const AffineAccessorRW h2osoi_liq(regions[1], task->regions[1].instance_fields[1]);
  const AffineAccessorRW h2osoi_ice(regions[1], task->regions[1].instance_fields[2]);
  const AffineAccessorRW t_soisno(regions[1], task->regions[1].instance_fields[3]);
  const AffineAccessorRW frac_iceold(regions[1], task->regions[1].instance_fields[4]);
  //const AffineAccessorRW snl(regions[1], task->regions[1].instance_fields[5]); // surface memeber 1D
  const AffineAccessorRW dz(regions[1], task->regions[1].instance_fields[5]);
  const AffineAccessorRW z(regions[1], task->regions[1].instance_fields[6]);
  const AffineAccessorRW zi(regions[1], task->regions[1].instance_fields[7]);

728
  // -- surface
729
  const AffineAccessorRO1 t_grnd(regions[2], task->regions[2].instance_fields[0]);
730
731
732
  const AffineAccessorRW1 h2osno(regions[2], task->regions[2].instance_fields[1]);
  const AffineAccessorRW1 snow_depth(regions[2], task->regions[2].instance_fields[2]);
  const AffineAccessorRW1 integrated_snow(regions[2], task->regions[2].instance_fields[3]);
733
734
735
736
737
738
  const AffineAccessorRO1 qflx_snow_grnd_col(regions[2], task->regions[2].instance_fields[4]);
  const AffineAccessorWO1 qflx_snow_h2osfc(regions[2], task->regions[2].instance_fields[5]); 
  const AffineAccessorWO1 qflx_floodc(regions[2], task->regions[2].instance_fields[6]);
  const AffineAccessorWO1 frac_snow_eff(regions[2], task->regions[2].instance_fields[7]);
  const AffineAccessorWO1 frac_sno(regions[2], task->regions[2].instance_fields[8]);
  const AffineAccessorRO1 frac_h2osfc(regions[2], task->regions[2].instance_fields[9]);
739
740
741
  const AffineAccessorRW1_int snow_level(regions[2], task->regions[2].instance_fields[10]);

  LogicalRegion lr = regions[2].get_logical_region();
742
743
  IndexSpaceT<1> is(lr.get_index_space());
  Rect<1> bounds = Domain(runtime->get_index_space_domain(is));
744

745
  //std::cout << "LOG: With bounds: " << bounds.lo << "," << bounds.hi << std::endl;
746
747
  
  int newnode = 0.;  
748
  for (int g = bounds.lo[0]; g != bounds.hi[0]+1; ++g) {
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
      ELM::CanopyHydrology_SnowWater(dtime, qflx_floodg,
              ltype, ctype, urbpoi, do_capsnow, oldfflag,
              forc_air_temp[lcv_time][g], t_grnd[g],
              qflx_snow_grnd_col[g], qflx_snow_melt, n_melt, frac_h2osfc[g],
              snow_depth[g], h2osno[g], integrated_snow[g], swe_old[g],
              h2osoi_liq[g], h2osoi_ice[g], t_soisno[g], frac_iceold[g],
              snow_level[g], dz[g], z[g], zi[g], newnode,
              qflx_floodc[g], qflx_snow_h2osfc[g], frac_snow_eff[g], frac_sno[g]);
  }
}


void
CanopyHydrology_SnowWater::preregister(TaskID new_taskid)
{
  // taskid = (taskid == AUTO_GENERATE_ID ?
  //           Legion::Runtime::generate_static_task_id() :
  //             new_taskid);
            
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<cpu_execute_task>(registrar, name.c_str());
}    

TaskID CanopyHydrology_SnowWater::taskid = TaskIDs::CANOPY_HYDROLOGY_SNOWWATER;
std::string CanopyHydrology_SnowWater::name = "canopy_hydrology_snowwater";






//
// CanopyHydrology FracH2OSfc task manager
//
// =============================================================================

FutureMap
CanopyHydrology_FracH2OSfc::launch(Context ctx, Runtime *runtime,
        Rect<1>& color_space,
        Data<2>& soil,
        Data<1>& surface)
{
  
  const int ltype = 1;
  const double dtime = 1800.0;
  const double micro_sigma = 0.1;
  const double min_h2osfc = 1.0e-8;

  auto args = std::make_tuple(dtime, min_h2osfc, micro_sigma ,ltype);
  ArgumentMap arg_map;
801
  IndexLauncher launcher(taskid,
802
803
          color_space, TaskArgument(&args, sizeof(args)), arg_map);

804
805
  // -- permissions on input
  launcher.add_region_requirement(
806
807
808
809
      RegionRequirement(surface.logical_partition, surface.projection_id,
                        READ_ONLY, EXCLUSIVE, surface.logical_region));
  std::vector<std::string> input{"h2osno"}; 
  for (auto fname1 : input)
810
    launcher.add_field(0,surface.field_ids[fname1]);
811
812


813
814
  // -- permissions on output
  launcher.add_region_requirement(
815
816
817
818
      RegionRequirement(soil.logical_partition, soil.projection_id,
                        READ_WRITE, EXCLUSIVE, soil.logical_region));
  std::vector<std::string> output{"h2osoi_liq"};
  for (auto fname : output)
819
820
821
822
    launcher.add_field(1,soil.field_ids[fname]);

  // -- permisions on surface output
  launcher.add_region_requirement(
823
  RegionRequirement(surface.logical_partition, surface.projection_id,
824
                        READ_WRITE, EXCLUSIVE, surface.logical_region));
825
  std::vector<std::string> output1{"h2osfc", "frac_h2osfc", "qflx_h2osfc2topsoi", "frac_snow_eff", "frac_sno"}; //h2osnow rw thing
826
  for (auto fname1 : output1)
827
    launcher.add_field(2,surface.field_ids[fname1]);
828
829

  // -- launch the interception
830
  return runtime->execute_index_space(ctx, launcher);
831
832
833
834
835
836
837
}

void
CanopyHydrology_FracH2OSfc::cpu_execute_task(const Task *task,
                 const std::vector<PhysicalRegion> &regions,
                 Context ctx, Runtime *runtime)
{
838
839
840
841
  assert(regions.size() == 3);
  assert(task->regions[0].instance_fields.size() == 1);
  assert(task->regions[1].instance_fields.size() == 1);
  assert(task->regions[2].instance_fields.size() == 5);
842
  //std::cout << "LOG: Executing FracH2OSfc task" << std::endl;
843
844
845
846
847
848
849
850

  double dtime, micro_sigma , min_h2osfc ;
  int ltype;
  using args_t = std::tuple<double,double,double,int>;
  std::tie(dtime, min_h2osfc, micro_sigma ,ltype) =
      *((args_t*) task->args);

  // get accessors
851
  using AffineAccessorRW2 = FieldAccessor<READ_WRITE,double,2,coord_t,
852
853
854
                                         Realm::AffineAccessor<double,2,coord_t> >;
  using AffineAccessorRO1 = FieldAccessor<READ_ONLY,double,1,coord_t,
                                         Realm::AffineAccessor<double,1,coord_t> >;                                         
855
  using AffineAccessorRW1 = FieldAccessor<READ_WRITE,double,1,coord_t,
856
                                         Realm::AffineAccessor<double,1,coord_t> >;
857
858
  // using AffineAccessorWO = FieldAccessor<WRITE_DISCARD,double,1,coord_t,
  //                                        Realm::AffineAccessor<double,1,coord_t> >;
859
  
860
861
862
863
864
865
866
867
868
869
870
871
  // -- input
  const AffineAccessorRO1 h2osno(regions[0], task->regions[0].instance_fields[0]);

  // -- output from soil
  const AffineAccessorRW2 h2osoi_liq(regions[1], task->regions[1].instance_fields[0]);

  // -- output from surface
  const AffineAccessorRW1 h2osfc(regions[2], task->regions[2].instance_fields[0]);
  const AffineAccessorRW1 frac_h2osfc(regions[2], task->regions[2].instance_fields[1]);
  const AffineAccessorRW1 qflx_h2osfc2topsoi(regions[2], task->regions[2].instance_fields[2]);
  const AffineAccessorRW1 frac_snow_eff(regions[2], task->regions[2].instance_fields[3]);
  const AffineAccessorRW1 frac_sno(regions[2], task->regions[2].instance_fields[4]);
872
  
873
  LogicalRegion lr = regions[2].get_logical_region();
874
875
876
  IndexSpaceT<1> is(lr.get_index_space());
  Rect<1> bounds = Domain(runtime->get_index_space_domain(is));

877
  //std::cout << "LOG: With bounds: " << bounds.lo << "," << bounds.hi << std::endl;
878
  for (int g = bounds.lo[0]; g != bounds.hi[0]+1; ++g) {
879
880
    ELM::CanopyHydrology_FracH2OSfc(dtime, min_h2osfc, ltype, micro_sigma,
            h2osno[g], h2osfc[g], h2osoi_liq[g][0], frac_sno[g], frac_snow_eff[g],qflx_h2osfc2topsoi[g], frac_h2osfc[g] );
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
  }
}


void
CanopyHydrology_FracH2OSfc::preregister(TaskID new_taskid)
{
             
  TaskVariantRegistrar registrar(taskid, name.c_str());
  registrar.add_constraint(ProcessorConstraint(Processor::LOC_PROC));
  registrar.set_leaf();
  Runtime::preregister_task_variant<cpu_execute_task>(registrar, name.c_str());
}    

TaskID CanopyHydrology_FracH2OSfc::taskid = TaskIDs::CANOPY_HYDROLOGY_FRACH2OS;
896
std::string CanopyHydrology_FracH2OSfc::name = "canopy_hydrology_frach2os";