• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GeodynamicWorldBuilder / WorldBuilder / 17164646845

22 Aug 2025 07:52PM UTC coverage: 98.013% (-0.5%) from 98.502%
17164646845

Pull #842

github

web-flow
Merge 7e708a65a into d543a0fff
Pull Request #842: [WIP] Initial draft of litho1.0 implementation.

152 of 195 new or added lines in 24 files covered. (77.95%)

3 existing lines in 1 file now uncovered.

8781 of 8959 relevant lines covered (98.01%)

162977.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.22
/source/world_builder/parameters.cc
1
/*
2
  Copyright (C) 2018-2024 by the authors of the World Builder code.
3

4
  This file is part of the World Builder.
5

6
   This program is free software: you can redistribute it and/or modify
7
   it under the terms of the GNU Lesser General Public License as published
8
   by the Free Software Foundation, either version 2 of the License, or
9
   (at your option) any later version.
10

11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU Lesser General Public License for more details.
15

16
   You should have received a copy of the GNU Lesser General Public License
17
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
18
*/
19

20

21
#include "world_builder/assert.h"
22
#include "world_builder/features/continental_plate_models/composition/interface.h"
23
#include "world_builder/features/continental_plate_models/velocity/interface.h"
24
#include "world_builder/features/continental_plate_models/grains/interface.h"
25
#include "world_builder/features/continental_plate_models/temperature/interface.h"
26
#include "world_builder/features/fault.h"
27
#include "world_builder/features/mantle_layer_models/composition/interface.h"
28
#include "world_builder/features/mantle_layer_models/grains/interface.h"
29
#include "world_builder/features/mantle_layer_models/temperature/interface.h"
30
#include "world_builder/features/mantle_layer_models/velocity/interface.h"
31
#include "world_builder/features/oceanic_plate_models/composition/interface.h"
32
#include "world_builder/features/oceanic_plate_models/grains/interface.h"
33
#include "world_builder/features/oceanic_plate_models/temperature/interface.h"
34
#include "world_builder/features/oceanic_plate_models/velocity/interface.h"
35
#include "world_builder/features/plume_models/composition/interface.h"
36
#include "world_builder/features/plume_models/grains/interface.h"
37
#include "world_builder/features/plume_models/temperature/interface.h"
38
#include "world_builder/features/plume_models/velocity/interface.h"
39
#include "world_builder/features/subducting_plate.h"
40
#include "world_builder/features/subducting_plate_models/velocity/interface.h"
41
#include "world_builder/gravity_model/interface.h"
42
#include "world_builder/types/object.h"
43
#include "world_builder/utilities.h"
44
#include "data/LITHO1.0/litho_coord_data.h"
45
#include "data/LITHO1.0/litho_depth_data.h"
46

47
#include "rapidjson/error/en.h"
48
#include "rapidjson/istreamwrapper.h"
49
#include "rapidjson/latexwriter.h"
50
#include "rapidjson/mystwriter.h"
51
#include "rapidjson/prettywriter.h"
52

53
#include <fstream>
54
#include <memory>
55

56
using namespace rapidjson;
57

58
namespace
59
{
60
  void remove_key(rapidjson::Value &value, const char *key)
10,451✔
61
  {
62
    if (value.IsObject())
10,451✔
63
      {
64
        auto it = value.FindMember(key);
2,348✔
65
        if (it != value.MemberEnd())
2,348✔
66
          value.RemoveMember(it);
1✔
67

68
        for (auto &member : value.GetObject())
11,619✔
69
          remove_key(member.value, key);
11,619✔
70

71
      }
72
    else if (value.IsArray())
8,103✔
73
      {
74
        for (auto &element : value.GetArray())
1,762✔
75
          remove_key(element, key);
1,762✔
76
      }
77
  }
10,451✔
78
}
79

80
namespace WorldBuilder
81
{
82
  Parameters::Parameters(World &world_)
155✔
83
    :
84
    world(world_)
465✔
85
  {
86
  }
155✔
87

88
  Parameters::~Parameters()
155✔
89
    = default;
90

91
  void Parameters::initialize(std::string &filename, bool has_output_dir, const std::string &output_dir)
153✔
92
  {
93

94
    if (has_output_dir)
153✔
95
      {
96
        StringBuffer buffer;
1✔
97
        std::ofstream file;
1✔
98

99
        // write out json schema
100
        file.open (output_dir + "world_builder_declarations.schema.json");
1✔
101
        WBAssertThrow(file.is_open(), "Error: Could not open file '" + output_dir + "world_builder_declarations.schema.json' for string the json declarations.");
1✔
102
        PrettyWriter<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> json_writer(buffer);
1✔
103
        declarations.Accept(json_writer);
1✔
104
        file << buffer.GetString();
1✔
105
        file.close();
1✔
106
        buffer.Clear();
1✔
107

108
        // remove Snippets so they don't appear in the documentation:
109
        remove_key(declarations, "defaultSnippets");
1✔
110

111
        // write out declarations
112
        file.open (output_dir + "world_builder_declarations.tex");
1✔
113
        WBAssertThrow(file.is_open(), "Error: Could not open file '" + output_dir + "world_builder_declarations.tex' for string the tex declarations.");
1✔
114

115
        LatexWriter<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> tex_writer(buffer);
1✔
116
        declarations.Accept(tex_writer);
1✔
117
        file << buffer.GetString();
1✔
118
        file.close();
1✔
119
        buffer.Clear();
1✔
120

121
        // write out declarations (open)
122
        file.open (output_dir + "world_builder_declarations_open.md");
1✔
123
        WBAssertThrow(file.is_open(), "Error: Could not open file '" + output_dir + "world_builder_declarations_open.md' for string the tex declarations.");
1✔
124

125
        MySTWriter<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> myst_writer_open(buffer, true);
1✔
126
        declarations.Accept(myst_writer_open);
1✔
127
        file << buffer.GetString();
1✔
128
        file.close();
1✔
129
        buffer.Clear();
1✔
130

131
        // write out declarations (closed)
132
        file.open (output_dir + "world_builder_declarations_closed.md");
1✔
133
        WBAssertThrow(file.is_open(), "Error: Could not open file '" + output_dir + "world_builder_declarations_closed.md' for string the tex declarations.");
1✔
134

135
        MySTWriter<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> myst_writer_closed(buffer, false);
1✔
136
        declarations.Accept(myst_writer_closed);
1✔
137
        file << buffer.GetString();
1✔
138
        file.close();
1✔
139
        buffer.Clear();
1✔
140
      }
1✔
141

142
    path_level =0;
153✔
143
    // Now read in the world builder file into a stringstream and
144
    // put it into a the rapidjson document
145
    std::stringstream json_input_stream(WorldBuilder::Utilities::read_and_distribute_file_content(filename));
153✔
146
    rapidjson::IStreamWrapper isw(json_input_stream);
152✔
147

148
    // relaxing syntax by allowing comments () for now, maybe also allow trailing commas and (kParseTrailingCommasFlag) and nan's, inf etc (kParseNanAndInfFlag)?
149
    //WBAssertThrow(!parameters.ParseStream<kParseCommentsFlag>(isw).HasParseError(), "Parsing errors world builder file");
150

151
    WBAssertThrowExc(!(parameters.ParseStream<kParseCommentsFlag | kParseNanAndInfFlag>(isw).HasParseError()), std::ifstream json_input_stream_error(filename.c_str()); ,
152✔
152
                     "Parsing errors world builder file: Error(offset " << static_cast<unsigned>(parameters.GetErrorOffset())
153
                     << "): " << GetParseError_En(parameters.GetParseError()) << std::endl << std::endl
154
                     << " Showing 50 chars before and after: "
155
                     << std::string((std::istreambuf_iterator<char>(json_input_stream_error.seekg(0, json_input_stream_error.beg))),
156
                                    std::istreambuf_iterator<char>()).substr(static_cast<unsigned>(parameters.GetErrorOffset()) <= 50
157
                                                                             ?
158
                                                                             0
159
                                                                             :
160
                                                                             static_cast<unsigned>(parameters.GetErrorOffset()) - 50, 100
161
                                                                            ) << std::endl << std::endl
162
                     << " Showing 5 chars before and after: "
163
                     << std::string((std::istreambuf_iterator<char>(json_input_stream_error.seekg(0, json_input_stream_error.beg))),
164
                                    std::istreambuf_iterator<char>()).substr(static_cast<unsigned>(parameters.GetErrorOffset()) <= 5
165
                                                                             ? 0
166
                                                                             :
167
                                                                             static_cast<unsigned>(parameters.GetErrorOffset())-5,
168
                                                                             (static_cast<unsigned>(parameters.GetErrorOffset()) + 10 > json_input_stream_error.seekg(0,std::ios::end).tellg()
169
                                                                              ?
170
                                                                              static_cast<unsigned>(json_input_stream.tellg())-static_cast<unsigned>(parameters.GetErrorOffset())
171
                                                                              :
172
                                                                              10)
173
                                                                            ));
174

175
    WBAssertThrow(parameters.IsObject(), "World builder file is is not an object.");
152✔
176

177

178
    const SchemaDocument schema(declarations);
152✔
179
    SchemaValidator validator(schema);
152✔
180

181
    if (!parameters.Accept(validator))
152✔
182
      {
183
        // Input JSON is invalid according to the schema
184
        // Output diagnostic information
185
        StringBuffer buffer;
1✔
186
        std::stringstream string;
1✔
187
        validator.GetInvalidSchemaPointer().StringifyUriFragment(buffer);
1✔
188
        string << "Invalid schema: " << buffer.GetString() << std::endl;
1✔
189
        string << "Invalid keyword: " << validator.GetInvalidSchemaKeyword();
1✔
190
        buffer.Clear();
1✔
191
        validator.GetInvalidDocumentPointer().StringifyUriFragment(buffer);
1✔
192
        string << "Invalid schema: " << buffer.GetString() << std::endl;
1✔
193
        PrettyWriter<StringBuffer> writer(buffer);
1✔
194
        validator.GetError().Accept(writer);
1✔
195
        WBAssertThrow(false, string.str() << "Error document: " << std::endl << buffer.GetString());
1✔
196
      }
3✔
197
  }
154✔
198

199
  void
200
  Parameters::declare_entry(const std::string &name,
193,072✔
201
                            const Types::Interface &type,
202
                            const std::string &documentation)
203
  {
204
    type.write_schema(*this,name,documentation);
193,072✔
205
  }
193,072✔
206

207
  bool
208
  Parameters::check_entry(const std::string &name) const
1,174✔
209
  {
210
    return Pointer((this->get_full_json_path() + "/" + name).c_str()).Get(parameters) != nullptr;
1,174✔
211
  }
212

213

214
  template<>
215
  std::string
216
  Parameters::get(const std::string &name)
5,311✔
217
  {
218
    const std::string base = this->get_full_json_path();
5,311✔
219
    const Value *value = Pointer((base + "/" + name).c_str()).Get(parameters);
5,311✔
220

221
#ifdef debug
222
    bool required = false;
223
    if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
224
      {
225
        for (auto &v : Pointer((base + "/required").c_str()).Get(declarations)->GetArray())
226
          {
227
            if (v.GetString() == name)
228
              {
229
                required = true;
230
              }
231
          }
232
      }
233

234
    WBAssert(value != NULL || required == false,
235
             "Internal error: Value \"" << base << '/' << name << "/type\" not found in the input file, while it was set as required.");
236
#endif
237
    if (value == nullptr)
5,311✔
238
      {
239
        value = Pointer((get_full_json_schema_path() + "/" + name + "/default value").c_str()).Get(declarations);
4,493✔
240
        WBAssertThrow(value != nullptr,
4,493✔
241
                      "internal error: could not retrieve the default value at: "
242
                      << base + "/" + name + "/default value");
243
      }
244

245
    return value->GetString();
10,620✔
246
  }
5,311✔
247

248
  template<>
249
  double
250
  Parameters::get(const std::string &name)
10,071✔
251
  {
252
    const std::string base = this->get_full_json_path();
10,071✔
253
    const Value *value = Pointer((base + "/" + name).c_str()).Get(parameters);
10,071✔
254

255
#ifdef debug
256
    bool required = false;
257
    if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
258
      {
259
        for (auto &v : Pointer((base + "/required").c_str()).Get(declarations)->GetArray())
260
          {
261
            if (v.GetString() == name)
262
              {
263
                required = true;
264
              }
265
          }
266
      }
267

268
    WBAssert(value != NULL || required == false,
269
             "Internal error: Value \"" << base << '/' << name << "/type\" not found in the input file, while it was set as required.");
270
#endif
271
    if (value == nullptr)
10,071✔
272
      {
273
        value = Pointer((get_full_json_schema_path() + "/" + name + "/default value").c_str()).Get(declarations);
5,465✔
274
        WBAssertThrow(value != nullptr,
5,465✔
275
                      "internal error: could not retrieve the default value at: "
276
                      << get_full_json_schema_path() + "/" + name + "/default value, for value: " << base + "/" + name);
277
      }
278

279
    double return_value;
280
    try
281
      {
282
        return_value = value->GetDouble();
10,070✔
283
      }
284
    catch (...)
1✔
285
      {
286
        WBAssertThrow(false, "Could not convert values of " << base << " into doubles.");
1✔
287
      }
1✔
288
    return return_value;
10,069✔
289
  }
10,071✔
290

291
  template<>
292
  size_t
293
  Parameters::get(const std::string &name)
2✔
294
  {
295
    const std::string base = this->get_full_json_path();
2✔
296
    const Value *value = Pointer((base + "/" + name).c_str()).Get(parameters);
2✔
297

298
#ifdef debug
299
    bool required = false;
300
    if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
301
      {
302
        for (auto &v : Pointer((base + "/required").c_str()).Get(declarations)->GetArray())
303
          {
304
            if (v.GetString() == name)
305
              {
306
                required = true;
307
              }
308
          }
309
      }
310

311
    WBAssert(value != NULL || required == false,
312
             "Internal error: Value \"" << base << '/' << name << "/type\" not found in the input file, while it was set as required.");
313
#endif
314
    if (value == nullptr)
2✔
315
      {
316
        value = Pointer((get_full_json_schema_path() + "/" + name + "/default value").c_str()).Get(declarations);
1✔
317
        WBAssertThrow(value != nullptr,
1✔
318
                      "internal error: could not retrieve the default value at: "
319
                      << base + "/" + name + "/default value");
320
      }
321

322
    return value->GetUint();
2✔
323
  }
2✔
324

325
  template<>
326
  unsigned int
327
  Parameters::get(const std::string &name)
301✔
328
  {
329
    const std::string base = this->get_full_json_path();
301✔
330
    const Value *value = Pointer((base + "/" + name).c_str()).Get(parameters);
301✔
331

332
#ifdef debug
333
    bool required = false;
334
    if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
335
      {
336
        for (auto &v : Pointer((base + "/required").c_str()).Get(declarations)->GetArray())
337
          {
338
            if (v.GetString() == name)
339
              {
340
                required = true;
341
              }
342
          }
343
      }
344

345
    WBAssert(value != NULL || required == false,
346
             "Internal error: Value \"" << base << '/' << name << "/type\" not found in the input file, while it was set as required.");
347
#endif
348
    if (value == nullptr)
301✔
349
      {
350
        value = Pointer((get_full_json_schema_path() + "/" + name + "/default value").c_str()).Get(declarations);
105✔
351
        WBAssertThrow(value != nullptr,
105✔
352
                      "internal error: could not retrieve the default value at: "
353
                      << base + "/" + name + "/default value");
354
      }
355

356
    return value->GetUint();
600✔
357
  }
301✔
358

359
  template<>
360
  int
361
  Parameters::get(const std::string &name)
152✔
362
  {
363
    const std::string base = this->get_full_json_path();
152✔
364
    const Value *value = Pointer((base + "/" + name).c_str()).Get(parameters);
152✔
365

366
#ifdef debug
367
    bool required = false;
368
    if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
369
      {
370
        for (auto &v : Pointer((base + "/required").c_str()).Get(declarations)->GetArray())
371
          {
372
            if (v.GetString() == name)
373
              {
374
                required = true;
375
              }
376
          }
377
      }
378

379
    WBAssert(value != NULL || required == false,
380
             "Internal error: Value \"" << base << '/' << name << "/type\" not found in the input file, while it was set as required.");
381
#endif
382
    if (value == nullptr)
152✔
383
      {
384
        value = Pointer((get_full_json_schema_path() + "/" + name + "/default value").c_str()).Get(declarations);
150✔
385
        WBAssertThrow(value != nullptr,
150✔
386
                      "internal error: could not retrieve the default value at: "
387
                      << base + "/" + name + "/default value");
388
      }
389

390
    return value->GetInt();
304✔
391
  }
152✔
392

393
  template<>
394
  bool
395
  Parameters::get(const std::string &name)
583✔
396
  {
397
    const std::string base = this->get_full_json_path();
583✔
398
    const Value *value = Pointer((base + "/" + name).c_str()).Get(parameters);
583✔
399

400
#ifdef debug
401
    bool required = false;
402
    if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
403
      {
404
        for (auto &v : Pointer((base + "/required").c_str()).Get(declarations)->GetArray())
405
          {
406
            if (v.GetString() == name)
407
              {
408
                required = true;
409
              }
410
          }
411
      }
412

413
    WBAssert(value != NULL || required == false,
414
             "Internal error: Value \"" << base << '/' << name << "/type\" not found in the input file, while it was set as required.");
415
#endif
416
    if (value == nullptr)
583✔
417
      {
418
        value = Pointer((get_full_json_schema_path() + "/" + name + "/default value").c_str()).Get(declarations);
486✔
419
        WBAssertThrow(value != nullptr,
486✔
420
                      "internal error: could not retrieve the default value at: "
421
                      << base + "/" + name + "/default value");
422
      }
423

424
    return value->GetBool();
1,166✔
425
  }
583✔
426

427

428
  template<>
429
  Point<2>
430
  Parameters::get(const std::string &name)
153✔
431
  {
432

433
    const std::string strict_base = this->get_full_json_path();
153✔
434
    const Value *array = Pointer((strict_base + "/" + name).c_str()).Get(parameters);
153✔
435

436
#ifdef debug
437
    bool required = false;
438
    if (Pointer((strict_base + "/required").c_str()).Get(declarations) != NULL)
439
      {
440
        for (auto &v : Pointer((strict_base + "/required").c_str()).Get(declarations)->GetArray())
441
          {
442
            if (v.GetString() == name)
443
              {
444
                required = true;
445
              }
446
          }
447
      }
448

449
    WBAssert(array != NULL || required == false,
450
             "Internal error: Value \"" << strict_base << '/' << name << "/type\" not found in the input file, while it was set as required.");
451
#endif
452
    if (array != nullptr)
153✔
453
      {
454
        const std::string base = strict_base + "/" + name;
153✔
455
        //let's assume that the file is correct, because it has been checked with the json schema.
456
        // So there are exactly two values.
457
        double value1;
458
        double value2;
459

460
        try
461
          {
462
            value1 = Pointer((base + "/0").c_str()).Get(parameters)->GetDouble();
155✔
463
            value2 = Pointer((base + "/1").c_str()).Get(parameters)->GetDouble();
152✔
464
          }
465
        catch (...)
1✔
466
          {
467
            WBAssertThrow(false, "Could not convert values of " << base << " into Point<2>, because it could not convert the sub-elements into doubles.");
1✔
468
          }
1✔
469
        return Point<2>(value1,value2,this->coordinate_system->natural_coordinate_system());
152✔
470
      }
153✔
471
    WBAssertThrow(false, "default values not implemented in get<Point<2> >. Looked in: " + strict_base + "/" << name);
×
472

473
    return {invalid};;
474
  }
153✔
475

476
  template<>
477
  std::vector<bool>
478
  Parameters::get_vector(const std::string &name)
138✔
479
  {
480
    std::vector<bool> vector;
138✔
481
    const std::string strict_base = this->get_full_json_path();
138✔
482
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
138✔
483
      {
484
        Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
136✔
485

486
        for (size_t i = 0; i < array->Size(); ++i )
338✔
487
          {
488
            const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
203✔
489

490
            vector.push_back(Pointer(base.c_str()).Get(parameters)->GetBool());
204✔
491
          }
203✔
492
      }
493
    else
494
      {
495
        const Value *value = Pointer((this->get_full_json_schema_path()  + "/" + name + "/minItems").c_str()).Get(declarations);
2✔
496
        WBAssertThrow(value != nullptr,
2✔
497
                      "internal error: could not retrieve the minItems value at: "
498
                      << this->get_full_json_schema_path() + "/" + name + "/minItems value");
499

500
        const size_t min_size = value->GetUint();
1✔
501

502
        const bool default_value = Pointer((this->get_full_json_schema_path()  + "/" + name + "/items/default value").c_str()).Get(declarations)->GetBool();
1✔
503

504
        // set to min size
505
        for (size_t i = 0; i < min_size; ++i)
3✔
506
          {
507
            vector.push_back(default_value);
2✔
508
          }
509
      }
510
    return vector;
272✔
511
  }
140✔
512

513

514
  std::pair<std::vector<double>,std::vector<double>>
515
                                                  Parameters::get(const std::string &name,
2,314✔
516
                                                                  const std::vector<Point<2> > &addition_points)
517
  {
518
    // There are four cases:
519
    // 1. No value provided: use the default value everywhere. Return first with one value and second with size 0.
520
    // 2. One double provided: use the default value everywhere. Return first with one value and second with size 0.
521
    // 3. One value in a double array and no points provided: use that value everywhere. Return first with one value and second with size 0.
522
    // 4. Other: fill the vectors with the default value and addition points and then add new point.
523
    // 5. A string provided: for example litho1 sediment 3, and a path provided?
524
    //    If a value without points is encountered, the additional points are used.
525
    std::pair<std::vector<double>,std::vector<double>> result;
2,314✔
526

527
    const std::string strict_base = this->get_full_json_path();
2,314✔
528

529
    // start with adding the additional points with the default value
530
    // to do this we need the default value
531
    double default_value = 0;
2,314✔
532
    enum InputTypes {DOUBLE_TYPE,ARRAY_TYPE,STRING_TYPE,MAX_INPUT_TYPES};
533
    InputTypes input_type = InputTypes::MAX_INPUT_TYPES;
2,314✔
534
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr && Pointer((strict_base + "/" + name).c_str()).Get(parameters)->IsArray())
2,314✔
535
      {
536
        input_type = InputTypes::ARRAY_TYPE;
264✔
537
        const std::string value_def_path = get_full_json_schema_path() + "/" + name + "/oneOf/1/items/items/anyOf/0/default value";
264✔
538
        Value *value_def = Pointer(value_def_path.c_str()).Get(declarations);
264✔
539
        WBAssertThrow(value_def != nullptr,
264✔
540
                      "internal error: could not retrieve the default value at: "
541
                      << value_def_path);
542

543
        // Since the default value is set in the code, if it fails it is an internal error, not a user error.
544
        // So no try/catch needed.
545
        default_value = value_def->GetDouble();
264✔
546
      }
264✔
547
    else if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr && Pointer((strict_base + "/" + name).c_str()).Get(parameters)->IsString())
2,050✔
548
      {
549
        input_type = InputTypes::STRING_TYPE;
1✔
550
        // I don't know if a default value makes sense here
551

552
      }
553
    else
554
      {
555
        input_type = InputTypes::DOUBLE_TYPE;
2,049✔
556
        Value *value_def = Pointer((get_full_json_schema_path() + "/" + name + "/oneOf/0/default value").c_str()).Get(declarations);
2,049✔
557
        WBAssertThrow(value_def != nullptr,
2,049✔
558
                      "internal error: could not retrieve the default value at: "
559
                      <<get_full_json_schema_path() + "/" + name + "/oneOf/0/default value");
560

561

562
        // Since the default value is set in the code, if it fails it is an internal error, not a user error.
563
        // So no try/catch needed.
564
        default_value = value_def->GetDouble();
2,048✔
565
      }
566

567

568
    // check if there is a user defined value
569
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
2,313✔
570
      {
571
        // there is a user defined value, so either case 2, 3 4, or 5.
572
        if (input_type == InputTypes::ARRAY_TYPE)
1,213✔
573
          {
574
            Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
264✔
575

576
            if (array->Size() == 1
792✔
577
                && Pointer((strict_base + "/" + name + "/0/1").c_str()).Get(parameters) == nullptr)
264✔
578
              {
579
                // case 2: Return first with one value and second with size 0.
580
                double value = 0;
14✔
581
                try
582
                  {
583
                    value = Pointer((strict_base + "/" + name + "/0/0").c_str()).Get(parameters)->GetDouble();
18✔
584
                  }
585
                catch (...)
1✔
586
                  {
587
                    WBAssertThrow(false, "Could not convert values of " << strict_base << "/" << name << "/0/0 into a double. "
1✔
588
                                  << "The provided value was \"" <<  Pointer((strict_base + "/" + name + "/0/0").c_str()).Get(parameters)->GetString() << "\".");
589
                  }
1✔
590
                result.first.emplace_back(value);
13✔
591
              }
592
            else
593
              {
594
                // case 3: fill the vectors with the default value and addition points and then add new point.
595
                //         If a value without points is encountered, the additional points are used.
596

597
                // first fill with additional points at default value
598
                for (const auto &addition_point : addition_points)
1,250✔
599
                  {
600
                    result.first.emplace_back(default_value);
1,000✔
601
                    result.second.emplace_back(addition_point[0]);
1,000✔
602
                    result.second.emplace_back(addition_point[1]);
1,000✔
603
                  }
604

605
                // second, go through all the points in order
606
                for (size_t i = 0; i < array->Size(); ++i )
753✔
607
                  {
608
                    // now parse a single value_at_point.
609
                    const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
506✔
610
                    // Let's assume that the file is correct, because it has been checked with the json schema.
611
                    // So there are exactly two values, the first value is a double, the second an array of 2d arrays (points).
612

613
                    // Get the double
614
                    double value;
615
                    Value *value_pointer = Pointer((base + "/0").c_str()).Get(parameters);
506✔
616

617
                    WBAssertThrow(value_pointer != nullptr, "internal error: this should not happen.");
506✔
618

619
                    try
620
                      {
621
                        value = value_pointer->GetDouble();
506✔
622
                      }
623
                    catch (...)
1✔
624
                      {
625
                        WBAssertThrow(false, "Could not convert values of " << base << "/0 into doubles. "
1✔
626
                                      << "The provided value was \"" <<  Pointer((base + "/0").c_str()).Get(parameters)->GetString() << "\".");
627
                      }
1✔
628

629
                    // now get the array of points.
630
                    Value *coordinates_array = Pointer((base + "/1").c_str()).Get(parameters);
505✔
631
                    if (coordinates_array != nullptr)
505✔
632
                      {
633
                        for (size_t coordinate_i = 0; coordinate_i < coordinates_array->Size(); ++coordinate_i )
910✔
634
                          {
635
                            // Let's assume that the file is correct, because it has been checked with the json schema.
636
                            // That means that there are exactly two values per item
637
                            double coordinate_0;
638
                            double coordinate_1;
639
                            try
640
                              {
641
                                coordinate_0 = Pointer((base + "/1/" + std::to_string(coordinate_i) + "/0").c_str()).Get(parameters)->GetDouble();
601✔
642
                              }
643
                            catch (...)
1✔
644
                              {
645
                                WBAssertThrow(false, "Could not convert values of " << base + "/1/" + std::to_string(coordinate_i) + "/0"
1✔
646
                                              << " into a Point<2> array, because it could not convert the 1st sub-elements into doubles. "
647
                                              << "The provided value was \""
648
                                              <<  Pointer((base + "/1/" + std::to_string(coordinate_i) + "/0").c_str()).Get(parameters)->GetString()
649
                                              << "\".");
650
                              }
1✔
651
                            try
652
                              {
653
                                coordinate_1 = Pointer((base + "/1/" + std::to_string(coordinate_i) + "/1").c_str()).Get(parameters)->GetDouble();
600✔
654
                              }
655
                            catch (...)
1✔
656
                              {
657
                                WBAssertThrow(false, "Could not convert values of " << base + "/1/" + std::to_string(coordinate_i) + "/1"
1✔
658
                                              << " into a Point<2> array, because it could not convert the 2nd sub-elements into doubles. "
659
                                              << "The provided value was \""
660
                                              <<  Pointer((base + "/1/" + std::to_string(coordinate_i) + "/1").c_str()).Get(parameters)->GetString()
661
                                              << "\".");
662
                              }
1✔
663

664
                            coordinate_0 *= (coordinate_system->natural_coordinate_system() == CoordinateSystem::spherical ? Consts::PI / 180.0 : 1.);
594✔
665
                            coordinate_1 *= (coordinate_system->natural_coordinate_system() == CoordinateSystem::spherical ? Consts::PI / 180.0 : 1.);
594✔
666

667
                            bool found_same_point = false;
594✔
668
                            unsigned int coordinate_pair_i = 0;
594✔
669
                            for (; coordinate_pair_i < result.second.size(); coordinate_pair_i+=2)
3,358✔
670
                              {
671
                                if (Utilities::approx(result.second[coordinate_pair_i],coordinate_0) && Utilities::approx(result.second[coordinate_pair_i+1],coordinate_1))
2,780✔
672
                                  {
673
                                    found_same_point = true;
16✔
674
                                    break;
16✔
675
                                  }
676
                              }
677
                            if (found_same_point)
594✔
678
                              {
679
                                // set the value to the new value
680
                                result.first[coordinate_pair_i/2] = value;
16✔
681
                              }
682
                            else
683
                              {
684
                                // add a new point
685
                                result.first.emplace_back(value);
578✔
686
                                result.second.emplace_back(coordinate_0);
578✔
687
                                result.second.emplace_back(coordinate_1);
578✔
688
                              }
689
                          }
690

691
                      }
692
                    else
693
                      {
694
                        // no points are provided, so use the value to fill put in the additional points
695
                        // at that value. Since we know that all the additional points are at the start
696
                        // we can easily overwrite the values.
697
                        for (unsigned int addition_point_i = 0; addition_point_i < addition_points.size(); ++addition_point_i)
945✔
698
                          {
699
                            result.first[addition_point_i] = value;
756✔
700
                          }
701
                      }
702
                  }
506✔
703
              }
704
          }
705
        else if (input_type == InputTypes::STRING_TYPE)
949✔
706
          {
707
            // case 5: a string. Get the string and decode it
708
            std::string value = "";
1✔
709

710
            try
711
              {
712
                value = Pointer((strict_base + "/" + name).c_str()).Get(parameters)->GetString();
1✔
713
              }
NEW
714
            catch (...)
×
715
              {
NEW
716
                WBAssertThrow(false, "Could not convert values of " << strict_base << "/" << name << " into a String. "
×
717
                              << "The provided value was \"" <<  Pointer((strict_base + "/" + name).c_str()).Get(parameters)->GetString() << "\".");
NEW
718
              }
×
719
            if (value.substr(0,8) == "Litho1.0")
1✔
720
              {
721
                enum LayerType
722
                {
723
                  // ASTHENOSPHERE,
724
                  LITHOSPHERE,
725
                  CRUST3,
726
                  CRUST2,
727
                  CRUST1,
728
                  SEDIMENT3,
729
                  SEDIMENT2,
730
                  SEDIMENT1,
731
                  ICE,
732
                  WATER,
733
                  MAX_LAYERTYPE
734
                };
NEW
735
                size_t colon_location = value.find(':');
×
NEW
736
                WBAssertThrow(colon_location!= std::string::npos,"when choosing Litho1.0 you need to specify a subunit with the colon (:)." );
×
NEW
737
                std::string rest_of_string = value.substr(colon_location); // TODO: improve and make more robust, look at gwb-dat example
×
NEW
738
                while ((!rest_of_string.empty()) && (rest_of_string[0] == ' '))
×
NEW
739
                  rest_of_string.erase(rest_of_string.begin());
×
NEW
740
                while ((!rest_of_string.empty()) && (rest_of_string[0] == ':'))
×
NEW
741
                  rest_of_string.erase(rest_of_string.begin());
×
NEW
742
                while ((!rest_of_string.empty()) && (rest_of_string[0] == ' '))
×
NEW
743
                  rest_of_string.erase(rest_of_string.begin());
×
NEW
744
                while ((!rest_of_string.empty()) && (rest_of_string[rest_of_string.size() - 1] == ' '))
×
NEW
745
                  rest_of_string.erase(rest_of_string.end() - 1);
×
NEW
746
                LayerType layer_type = LayerType::MAX_LAYERTYPE;
×
NEW
747
                if (rest_of_string == "lithosphere")
×
748
                  {
NEW
749
                    layer_type = LayerType::LITHOSPHERE;
×
750
                  }
NEW
751
                else if (rest_of_string == "crust 3")
×
752
                  {
NEW
753
                    layer_type = LayerType::CRUST3;
×
754
                  }
NEW
755
                else if (rest_of_string == "crust 2")
×
756
                  {
NEW
757
                    layer_type = LayerType::CRUST2;
×
758
                  }
NEW
759
                else if (rest_of_string == "crust 1")
×
760
                  {
NEW
761
                    layer_type = LayerType::CRUST1;
×
762
                  }
NEW
763
                else if (rest_of_string == "sediment 3")
×
764
                  {
NEW
765
                    layer_type = LayerType::SEDIMENT3;
×
766
                  }
NEW
767
                else if (rest_of_string == "sediment 2")
×
768
                  {
NEW
769
                    layer_type = LayerType::SEDIMENT2;
×
770
                  }
NEW
771
                else if (rest_of_string == "sediment 1")
×
772
                  {
NEW
773
                    layer_type = LayerType::SEDIMENT1;
×
774
                  }
NEW
775
                else if (rest_of_string == "ice")
×
776
                  {
NEW
777
                    layer_type = LayerType::ICE;
×
778
                  }
NEW
779
                else if (rest_of_string == "water")
×
780
                  {
NEW
781
                    layer_type = LayerType::WATER;
×
782
                  }
NEW
783
                WBAssertThrow(layer_type != LayerType::MAX_LAYERTYPE, "Could not find litho1.0 layer type " << rest_of_string);
×
784
                //std::string litho_1_0_path = "";
785
                //Value *value_pointer = Pointer("/Litho1.0 path").Get(parameters);
786
                //WBAssertThrow(value_pointer != nullptr, "You are using the Litho1.0 dataset, but you have not specified the path to the dataset. Please add below \"version\": \"Litho1.0 path\". ");
787
                //try
788
                //  {
789
                //    litho_1_0_path = value_pointer->GetString();
790
                //  }
791
                //catch (...)
792
                //  {
793
                //    WBAssertThrow(false, "Could not convert values of /Litho1.0 path into a String. ");
794
                //  }
795

NEW
796
                constexpr int n1 = 40962;
×
NEW
797
                constexpr int n_layers = 9;
×
798

799
                //std::vector<float> depth_data(n1 * n_layers,0);
800
                ////std::cout << depth_data[0] << std::endl;
801
                //char tessfile[255];
802
                //snprintf(tessfile, 254, "%s/litho_depth_data.bin", litho_1_0_path.c_str());
803

804
                //FILE *fptrb = nullptr;
805
                //if ((fptrb = fopen(tessfile, "rb")) == nullptr)
806
                //  {
807
                //    WBAssertThrow(false, "ERROR: Could not open file " << tessfile);
808
                //  }
809
                //const size_t ret_code = fread(&depth_data, sizeof(depth_data), 1, fptrb);
810
                //WBAssertThrow(ret_code == n1 * n_layers, "Error in reading the Litho1.0 data.");
811
                //fclose(fptrb);
812

813
                //snprintf(tessfile, 254, "%s/Icosahedron_Level7_LatLon_mod.txt",
814
                //         litho_1_0_path.c_str());
815
                //FILE *fp = nullptr;
816
                //if ((fp = fopen(tessfile, "r")) == nullptr)
817
                //  {
818
                //    WBAssertThrow(false, "ERROR: Could not open file " << tessfile);
819
                //  }
820

821
                //size_t counter_location_data = 0;
822
                //float latitude, glatitude, longitude = 0;
823
                //while (fscanf(fp, "%f %f %f", &latitude, &glatitude, &longitude) != EOF)
824
                //  {
825
                //    const size_t global_index = (counter_location_data/2)*n_layers+static_cast<size_t> (layer_type);
826
                //    result.first.emplace_back(depth_data[global_index]);
827
                //    result.second.emplace_back(longitude * Consts::PI / 180.);
828
                //    result.second.emplace_back(latitude * Consts::PI / 180.);
829
                //    counter_location_data += 2;
830
                //  }
831

832
                //fclose(fp);
NEW
833
                for (size_t index = 0; index < n1; ++index )
×
834
                  {
835

NEW
836
                    const size_t global_index = index*n_layers+static_cast<size_t> (layer_type);
×
NEW
837
                    result.first.emplace_back(Datasets::LITHO1_0::depths[global_index]);
×
NEW
838
                    result.second.emplace_back(Datasets::LITHO1_0::coordinates_lat_long[index*2] * Consts::PI / 180.);
×
NEW
839
                    result.second.emplace_back(Datasets::LITHO1_0::coordinates_lat_long[index*2+1] * Consts::PI / 180.);
×
840
                  }
841

NEW
842
              }
×
843
            else
844
              {
845
                WBAssertThrow(false,"Could not find \"" << value << "\" in \"" << strict_base << "/" << name << "\". ");
1✔
846
              }
NEW
847
            WBAssertThrow(result.first.size() > 0,"Internal error: program should not get here.");
×
848
          }
1✔
849
        else
850
          {
851
            // case 2: there one value, not an array
852
            double value = 0;
948✔
853
            try
854
              {
855
                value = Pointer((strict_base + "/" + name).c_str()).Get(parameters)->GetDouble();
948✔
856
              }
UNCOV
857
            catch (...)
×
858
              {
UNCOV
859
                WBAssertThrow(false, "Could not convert values of " << strict_base << "/" << name << " into a double. "
×
860
                              << "The provided value was \"" <<  Pointer((strict_base + "/" + name).c_str()).Get(parameters)->GetString() << "\".");
UNCOV
861
              }
×
862
            result.first.emplace_back(value);
948✔
863
          }
864
      }
865
    else
866
      {
867
        // there is no user defined value. Case one: return the default value and no points
868
        result.first.emplace_back(default_value);
1,100✔
869
      }
870
    WBAssertThrow(result.first.size() > 0, "Internal error: no entries returned when fetching value at points.");
2,308✔
871
    return result;
4,616✔
872
  }
2,320✔
873

874

875
  std::pair<std::vector<double>,std::vector<double>> Parameters::get_value_at_array(const std::string &name)
161✔
876
  {
877
    // There are two cases:
878
    // 1. One double provided: use the default value everywhere. Return first with one value and second with size 0.
879
    // 2. Other: fill the vectors with the default value and addition points and then add new point.
880
    //    If a value without points is encountered, the additional points are used.
881
    std::pair<std::vector<double>,std::vector<double>> result;
161✔
882

883
    const std::string strict_base = this->get_full_json_path();
161✔
884

885
    // start with adding the additional points with the default value
886
    // to do this we need the default value
887
    double default_value = 0;
161✔
888
    bool is_array = true;
161✔
889
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr && Pointer((strict_base + "/" + name).c_str()).Get(parameters)->IsArray())
161✔
890
      {
891
        const std::string value_def_path = get_full_json_schema_path() + "/" + name + "/oneOf/1/items/items/anyOf/0/default value";
7✔
892
        Value *value_def = Pointer(value_def_path.c_str()).Get(declarations);
7✔
893
        WBAssertThrow(value_def != nullptr,
7✔
894
                      "internal error: could not retrieve the default value at: "
895
                      << value_def_path);
896

897
        // Since the default value is set in the code, if it fails it is an internal error, not a user error.
898
        // So no try/catch needed.
899
        default_value = value_def->GetDouble();
7✔
900
      }
7✔
901
    else
902
      {
903
        is_array = false;
154✔
904
        Value *value_def = Pointer((get_full_json_schema_path() + "/" + name + "/oneOf/0/default value").c_str()).Get(declarations);
154✔
905
        WBAssertThrow(value_def != nullptr,
154✔
906
                      "internal error: could not retrieve the default value at: "
907
                      <<get_full_json_schema_path() + "/" + name + "/oneOf/0/default value");
908

909

910
        // Since the default value is set in the code, if it fails it is an internal error, not a user error.
911
        // So no try/catch needed.
912
        default_value = value_def->GetDouble();
154✔
913
      }
914

915

916
    // check if there is a user defined value
917
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
161✔
918
      {
919
        // there is a user defined value, so either case 2, 3 or 4.
920
        if (is_array)
160✔
921
          {
922
            Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
7✔
923

924
            // go through all the points in order
925
            for (size_t i = 0; i < array->Size(); ++i )
18✔
926
              {
927
                // now parse a single value_at_point.
928
                const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
11✔
929
                // Let's assume that the file is correct, because it has been checked with the json schema.
930
                // So there are exactly two values, the first value is a double, the second an array of 2d arrays (points).
931

932
                // Get the double
933
                double value;
934
                Value *value_pointer = Pointer((base + "/0").c_str()).Get(parameters);
11✔
935

936
                WBAssertThrow(value_pointer != nullptr, "internal error: this should not happen.");
11✔
937

938
                try
939
                  {
940
                    value = value_pointer->GetDouble();
11✔
941
                  }
942
                catch (...)
×
943
                  {
944
                    WBAssertThrow(false, "Could not convert values of " << base << "/0 into doubles. "
×
945
                                  << "The provided value was \"" <<  Pointer((base + "/0").c_str()).Get(parameters)->GetString() << "\".");
946
                  }
×
947

948
                // now get the array of points.
949
                Value *array_of_doubles = Pointer((base + "/1").c_str()).Get(parameters);
11✔
950
                double value_in_array;
951
                if (array_of_doubles != nullptr)
11✔
952
                  {
953
                    for (size_t coordinate_i = 0; coordinate_i < array_of_doubles->Size(); ++coordinate_i )
22✔
954
                      {
955
                        Value *coordinate_j_array = Pointer((base + "/1/" + std::to_string(coordinate_i)).c_str()).Get(parameters);
11✔
956
                        for (size_t coordinate_j = 0; coordinate_j < coordinate_j_array->Size(); ++coordinate_j)
37✔
957
                          {
958
                            // Let's assume that the file is correct, because it has been checked with the json schema.
959
                            // That means that there are exactly two values per item
960
                            try
961
                              {
962
                                value_in_array = Pointer((base + "/1/" + std::to_string(coordinate_i) + "/" + std::to_string(coordinate_j)).c_str()).Get(parameters)->GetDouble();
26✔
963
                              }
964
                            catch (...)
×
965
                              {
966
                                WBAssertThrow(false, "Could not convert values of " << base + "/1/" + std::to_string(coordinate_i) + "/" + std::to_string(coordinate_j)
×
967
                                              << " into a Point<2> array, because it could not convert the 1st sub-elements into doubles. "
968
                                              << "The provided value was \""
969
                                              <<  Pointer((base + "/1/" + std::to_string(coordinate_i) + "/" + std::to_string(coordinate_j)).c_str()).Get(parameters)->GetString()
970
                                              << "\".");
971
                              }
×
972

973
                            result.second.emplace_back(value_in_array);
26✔
974
                          }
975
                      }
976
                    result.first.emplace_back(value);
11✔
977
                  }
978
              }
11✔
979
          }
980
        else
981
          {
982
            // case 1: there one value, not an array
983
            double value = 0;
153✔
984
            try
985
              {
986
                value = Pointer((strict_base + "/" + name).c_str()).Get(parameters)->GetDouble();
153✔
987
              }
988
            catch (...)
×
989
              {
990
                WBAssertThrow(false, "Could not convert values of " << strict_base << "/" << name << " into a double. "
×
991
                              << "The provided value was \"" <<  Pointer((strict_base + "/" + name).c_str()).Get(parameters)->GetString() << "\".");
992
              }
×
993
            result.first.emplace_back(0.0);
153✔
994
            result.second.emplace_back(value);
153✔
995
          }
996
      }
997
    else
998
      {
999
        // there is no user defined value. Case one: return the default value and no points
1000
        result.first.emplace_back(0.0);
1✔
1001
        result.second.emplace_back(default_value);
1✔
1002
      }
1003

1004
    return result;
322✔
1005
  }
161✔
1006

1007

1008
  template<>
1009
  std::vector<Point<2> >
1010
  Parameters::get_vector(const std::string &name)
585✔
1011
  {
1012
    std::vector<Point<2> > vector;
585✔
1013
    const std::string strict_base = this->get_full_json_path();
585✔
1014
    WBAssertThrow(Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr,"Error: " << name
585✔
1015
                  << " was not defined in " << strict_base << ", schema path: " << this->get_full_json_schema_path() << ".");
1016

1017
    Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
585✔
1018

1019
    for (size_t i = 0; i < array->Size(); ++i )
4,389✔
1020
      {
1021
        const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
3,805✔
1022
        //let's assume that the file is correct, because it has been checked with the json schema.
1023
        // So there are exactly two values.
1024
        double value1;
1025
        double value2;
1026

1027
        try
1028
          {
1029
            value1 = Pointer((base + "/0").c_str()).Get(parameters)->GetDouble();
3,805✔
1030
            value2 = Pointer((base + "/1").c_str()).Get(parameters)->GetDouble();
3,807✔
1031
          }
1032
        catch (...)
1✔
1033
          {
1034
            WBAssertThrow(false, "Could not convert values of " << base << " into a Point<2> array, because it could not convert the sub-elements into doubles.");
1✔
1035
          }
1✔
1036
        vector.emplace_back(value1,value2,this->coordinate_system->natural_coordinate_system());
3,804✔
1037
      }
3,805✔
1038

1039
    return vector;
1,168✔
1040
  }
586✔
1041

1042
  template<>
1043
  std::vector<std::array<double,3> >
1044
  Parameters::get_vector(const std::string &name)
407✔
1045
  {
1046
    std::vector<std::array<double,3> > vector;
407✔
1047
    const std::string strict_base = this->get_full_json_path();
407✔
1048
    WBAssertThrow(Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr,"Error: " << name
407✔
1049
                  << " was not defined in " << strict_base << ", schema path: " << this->get_full_json_schema_path() << ".");
1050

1051
    Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
407✔
1052

1053
    for (size_t i = 0; i < array->Size(); ++i )
1,207✔
1054
      {
1055
        const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
801✔
1056
        //let's assume that the file is correct, because it has been checked with the json schema.
1057
        // So there are exactly three values.
1058
        try
1059
          {
1060
            const double value1 = Pointer((base + "/0").c_str()).Get(parameters)->GetDouble();
801✔
1061
            const double value2 = Pointer((base + "/1").c_str()).Get(parameters)->GetDouble();
801✔
1062
            const double value3 = Pointer((base + "/2").c_str()).Get(parameters)->GetDouble();
803✔
1063
            vector.push_back({{value1,value2,value3}});
800✔
1064
          }
1065
        catch (...)
1✔
1066
          {
1067
            WBAssertThrow(false, "Could not convert values of " << base << " into doubles.");
1✔
1068
          }
1✔
1069
      }
801✔
1070

1071

1072
    return vector;
812✔
1073
  }
408✔
1074

1075
  std::vector<std::vector<double>>
1076
                                Parameters::get_vector_or_double(const std::string &name)
96✔
1077
  {
1078
    // There are two cases:
1079
    // 1. One double provided: use the default value everywhere. Return first with one value and second with size 0.
1080
    // 2. std::vector<std::vector<double>> provided: output this array.
1081
    std::vector<std::vector<double>> result;
96✔
1082

1083
    const std::string strict_base = this->get_full_json_path();
96✔
1084

1085
    // start with adding the additional points with the default value
1086
    // to do this we need the default value
1087
    double default_value = 0;
96✔
1088
    bool is_array = true;
96✔
1089
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr && Pointer((strict_base + "/" + name).c_str()).Get(parameters)->IsArray())
96✔
1090
      {
1091
        const std::string value_def_path = get_full_json_schema_path() + "/" + name + "/oneOf/1/items/items/default value";
5✔
1092
        Value *value_def = Pointer(value_def_path.c_str()).Get(declarations);
5✔
1093
        WBAssertThrow(value_def != nullptr,
5✔
1094
                      "internal error: could not retrieve the default value at: "
1095
                      << value_def_path);
1096

1097
        // Since the default value is set in the code, if it fails it is an internal error, not a user error.
1098
        // So no try/catch needed.
1099
        default_value = value_def->GetDouble();
5✔
1100
      }
5✔
1101
    else
1102
      {
1103
        is_array = false;
91✔
1104
        Value *value_def = Pointer((get_full_json_schema_path() + "/" + name + "/oneOf/0/default value").c_str()).Get(declarations);
91✔
1105
        WBAssertThrow(value_def != nullptr,
91✔
1106
                      "internal error: could not retrieve the default value at: "
1107
                      <<get_full_json_schema_path() + "/" + name + "/oneOf/0/default value");
1108

1109

1110
        // Since the default value is set in the code, if it fails it is an internal error, not a user error.
1111
        // So no try/catch needed.
1112
        default_value = value_def->GetDouble();
91✔
1113
      }
1114

1115

1116
    // check if there is a user defined value
1117
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
96✔
1118
      {
1119
        // there is a user defined value, so either case 2, 3 or 4.
1120
        if (is_array)
96✔
1121
          {
1122
            Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
5✔
1123

1124
            // go through all the 1d-arrays within the 2d-array
1125
            for (size_t i = 0; i < array->Size(); ++i )
11✔
1126
              {
1127
                // now parse a single value_at_point.
1128
                const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
6✔
1129

1130
                // now get the array of points.
1131
                // Value *coordinates_array = Pointer((base + "/0").c_str()).Get(parameters);
1132
                Value *coordinates_array = Pointer((base).c_str()).Get(parameters);
6✔
1133
                double value_in_array;
1134
                std::vector<double> array_of_values;
6✔
1135
                if (coordinates_array != nullptr)
6✔
1136
                  {
1137
                    for (size_t coordinate_i = 0; coordinate_i < coordinates_array->Size(); ++coordinate_i )
20✔
1138
                      {
1139
                        // Let's assume that the file is correct, because it has been checked with the json schema.
1140
                        // That means that there are exactly two values per item
1141
                        try
1142
                          {
1143
                            value_in_array = Pointer(((base + "/") + std::to_string(coordinate_i)).c_str()).Get(parameters)->GetDouble();
14✔
1144
                          }
1145
                        catch (...)
×
1146
                          {
1147
                            WBAssertThrow(false, "Could not convert values of " << base + "/" + std::to_string(i) + "/" + std::to_string(coordinate_i) + "/" + std::to_string(coordinate_i)
×
1148
                                          << " into a Point<2> array, because it could not convert the 1st sub-elements into doubles. "
1149
                                          << "The provided value was \""
1150
                                          <<  Pointer((base + "/" + std::to_string(i) + "/" + std::to_string(coordinate_i)).c_str()).Get(parameters)->GetString()
1151
                                          << "\".");
1152
                          }
×
1153
                        array_of_values.emplace_back(value_in_array);
14✔
1154
                      }
1155
                    result.emplace_back(array_of_values);
6✔
1156

1157
                  }
1158
              }
6✔
1159
          }
1160
        else
1161
          {
1162
            // case 1: there's one value, not an array
1163
            double value = 0;
91✔
1164
            try
1165
              {
1166
                value = Pointer((strict_base + "/" + name).c_str()).Get(parameters)->GetDouble();
91✔
1167
              }
1168
            catch (...)
×
1169
              {
1170
                WBAssertThrow(false, "Could not convert values of " << strict_base << "/" << name << " into a double. "
×
1171
                              << "The provided value was \"" <<  Pointer((strict_base + "/" + name).c_str()).Get(parameters)->GetString() << "\".");
1172
              }
×
1173
            result.emplace_back(std::vector<double> {value});
273✔
1174
          }
1175
      }
1176
    else
1177
      {
1178
        // there is no user defined value. Case one: return the default value and no points
1179
        result.emplace_back(std::vector<double> {default_value});
×
1180
      }
1181

1182
    return result;
192✔
1183
  }
96✔
1184

1185

1186

1187
  template<>
1188
  std::vector<std::array<std::array<double,3>,3> >
1189
  Parameters::get_vector(const std::string &name)
109✔
1190
  {
1191
    std::vector<std::array<std::array<double,3>,3>  > vector;
109✔
1192
    const std::string strict_base = this->get_full_json_path();
109✔
1193
    WBAssertThrow(Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr,"Error: " << name
109✔
1194
                  << " was not defined in " << strict_base << ", schema path: " << this->get_full_json_schema_path() << ".");
1195

1196
    Value *array1 = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
109✔
1197

1198
    for (size_t i = 0; i < array1->Size(); ++i )
310✔
1199
      {
1200
        const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
204✔
1201
        Value *array2 = Pointer((base).c_str()).Get(parameters);
204✔
1202

1203
        // Not sure why cppcheck it is generating the warning
1204
        // Filed a question at: https://sourceforge.net/p/cppcheck/discussion/general/thread/429759f85e/
1205
        // cppcheck-suppress constStatement
1206
        std::array<std::array<double,3>,3> array;
1207
        WBAssertThrow(array2->Size() == 3, "Array " << i << " is supposed to be a 3x3 array, but the outer array dimensions is "
204✔
1208
                      << array2->Size() << '.');
1209
        for (size_t j = 0; j < array2->Size(); ++j )
806✔
1210
          {
1211
            const std::string base_extended = base + "/" + std::to_string(j);
605✔
1212

1213
            WBAssertThrow(Pointer((base_extended).c_str()).Get(parameters)->Size() == 3,
605✔
1214
                          "Array " << i << " is supposed to be a 3x3 array, but the inner array dimensions of "
1215
                          << j << " is " << Pointer((base_extended).c_str()).Get(parameters)->Size() << '.');
1216
            double value1;
1217
            double value2;
1218
            double value3;
1219

1220
            try
1221
              {
1222
                value1 = Pointer((base_extended + "/0").c_str()).Get(parameters)->GetDouble();
604✔
1223
                value2 = Pointer((base_extended + "/1").c_str()).Get(parameters)->GetDouble();
604✔
1224
                value3 = Pointer((base_extended + "/2").c_str()).Get(parameters)->GetDouble();
606✔
1225
              }
1226
            catch (...)
1✔
1227
              {
1228
                WBAssertThrow(false, "Could not convert values of " << base << " into doubles.");
1✔
1229
              }
1✔
1230
            array[j][0] = value1;
603✔
1231
            array[j][1] = value2;
603✔
1232
            array[j][2] = value3;
603✔
1233
          }
605✔
1234
        vector.push_back(array);
201✔
1235
      }
204✔
1236

1237
    return vector;
212✔
1238
  }
112✔
1239

1240

1241
  template<>
1242
  std::vector<std::vector<Point<2> > >
1243
  Parameters::get_vector(const std::string &name)
160✔
1244
  {
1245
    std::vector<std::vector<Point<2> >  > vector;
160✔
1246
    const std::string strict_base = this->get_full_json_path();
160✔
1247
    WBAssertThrow(Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr,"Error: " << name
160✔
1248
                  << " was not defined in " << strict_base << ", schema path: " << this->get_full_json_schema_path() << ".");
1249

1250
    Value *array1 = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
160✔
1251

1252
    for (size_t i = 0; i < array1->Size(); ++i )
331✔
1253
      {
1254
        const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
172✔
1255
        Value *array2 = Pointer((base).c_str()).Get(parameters);
172✔
1256

1257
        // Not sure why cppcheck it is generating the warning
1258
        // Filed a question at: https://sourceforge.net/p/cppcheck/discussion/general/thread/429759f85e/
1259
        // cppcheck-suppress constStatement
1260
        std::vector<Point<2> > sub_vector(array2->Size(),Point<2>(NaN::DSNAN,NaN::DSNAN,coordinate_system->natural_coordinate_system()));
172✔
1261
        for (size_t j = 0; j < array2->Size(); ++j )
527✔
1262
          {
1263
            const std::string base_extended = base + "/" + std::to_string(j);
356✔
1264

1265
            WBAssertThrow(Pointer((base_extended).c_str()).Get(parameters)->Size() == 2,
356✔
1266
                          "Array " << i << " is supposed to be a 2d point, but the inner array dimensions of "
1267
                          << j << " is " << Pointer((base_extended).c_str()).Get(parameters)->Size() << '.');
1268
            double value1;
1269
            double value2;
1270

1271
            try
1272
              {
1273
                value1 = Pointer((base_extended + "/0").c_str()).Get(parameters)->GetDouble();
358✔
1274
                value2 = Pointer((base_extended + "/1").c_str()).Get(parameters)->GetDouble();
355✔
1275
              }
1276
            catch (...)
1✔
1277
              {
1278
                WBAssertThrow(false, "Could not convert values of " << base << " into doubles, because it could not covert the sub-elements into doubles.");
1✔
1279
              }
1✔
1280
            sub_vector[j][0] = value1;
355✔
1281
            sub_vector[j][1] = value2;
355✔
1282
          }
356✔
1283
        vector.push_back(sub_vector);
171✔
1284
      }
173✔
1285

1286
    return vector;
318✔
1287
  }
161✔
1288

1289

1290
  template<>
1291
  std::vector<Objects::Segment<Features::SubductingPlateModels::Temperature::Interface,
1292
      Features::SubductingPlateModels::Composition::Interface,
1293
      Features::SubductingPlateModels::Grains::Interface,
1294
      Features::SubductingPlateModels::Velocity::Interface> >
1295
      Parameters::get_vector(const std::string &name,
201✔
1296
                             std::vector<std::shared_ptr<Features::SubductingPlateModels::Temperature::Interface> > &default_temperature_models,
1297
                             std::vector<std::shared_ptr<Features::SubductingPlateModels::Composition::Interface> > &default_composition_models,
1298
                             std::vector<std::shared_ptr<Features::SubductingPlateModels::Grains::Interface> > &default_grains_models,
1299
                             std::vector<std::shared_ptr<Features::SubductingPlateModels::Velocity::Interface> > &default_velocity_models)
1300
  {
1301
    using namespace Features::SubductingPlateModels;
1302
    std::vector<Objects::Segment<Temperature::Interface,Composition::Interface,Grains::Interface,Velocity::Interface> > vector;
201✔
1303
    this->enter_subsection(name);
201✔
1304
    const std::string strict_base = this->get_full_json_path();
201✔
1305
    WBAssertThrow(Pointer((strict_base).c_str()).Get(parameters) != nullptr,"Error: " << name
201✔
1306
                  << " was not defined in " << strict_base << ", schema path: " << this->get_full_json_schema_path() << ".");
1307

1308
    // get the array of segments
1309
    Value *array = Pointer((strict_base).c_str()).Get(parameters);
201✔
1310

1311
    for (size_t i = 0; i < array->Size(); ++i )
795✔
1312
      {
1313
        this->enter_subsection(std::to_string(i));
594✔
1314
        const std::string base = this->get_full_json_path();
594✔
1315
        // get one segment
1316
        // length
1317
        const double length = Pointer((base + "/length").c_str()).Get(parameters)->GetDouble();
594✔
1318

1319
        // get thickness
1320
        Value *point_array = Pointer((base  + "/thickness").c_str()).Get(parameters);
594✔
1321
        Point<2> thickness(invalid);
594✔
1322
        WBAssertThrow(point_array != nullptr,"error: " << name
594✔
1323
                      << " was not defined in " << strict_base << "/thickness, schema path: " << this->get_full_json_schema_path() << "/thickness.");
1324

1325
        if (point_array->Size() == 1)
594✔
1326
          {
1327
            // There is only one value, set it for both elements
1328
            const double local0 = Pointer((base + "/thickness/0").c_str()).Get(parameters)->GetDouble();
413✔
1329
            thickness = Point<2>(local0,local0,invalid);
413✔
1330
          }
1331
        else
1332
          {
1333
            const double local0 = Pointer((base + "/thickness/0").c_str()).Get(parameters)->GetDouble();
181✔
1334
            const double local1 = Pointer((base + "/thickness/1").c_str()).Get(parameters)->GetDouble();
181✔
1335
            thickness = Point<2>(local0,local1,invalid);
181✔
1336
          }
1337

1338

1339
        // get top truncation (default is 0,0)
1340
        point_array = Pointer((base  + "/top truncation").c_str()).Get(parameters);
594✔
1341
        Point<2> top_truncation(invalid);
594✔
1342
        if (point_array != nullptr)
594✔
1343
          {
1344
            if (point_array->Size() == 1)
149✔
1345
              {
1346
                // There is only one value, set it for both elements
1347
                const double local0 = Pointer((base + "/top truncation/0").c_str()).Get(parameters)->GetDouble();
133✔
1348
                top_truncation = Point<2>(local0,local0,invalid);
133✔
1349
              }
1350
            else
1351
              {
1352
                const double local0 = Pointer((base + "/top truncation/0").c_str()).Get(parameters)->GetDouble();
16✔
1353
                const double local1 = Pointer((base + "/top truncation/1").c_str()).Get(parameters)->GetDouble();
16✔
1354
                top_truncation = Point<2>(local0,local1,invalid);
16✔
1355
              }
1356
          }
1357
        // get thickness
1358
        point_array = Pointer((base  + "/angle").c_str()).Get(parameters);
594✔
1359
        Point<2> angle(invalid);
594✔
1360
        WBAssertThrow(point_array != nullptr,"error: " << name
594✔
1361
                      << " was not defined in " << strict_base << "/angle, schema path: " << this->get_full_json_schema_path() << "/angle.");
1362

1363
        if (point_array->Size() == 1)
594✔
1364
          {
1365
            // There is only one value, set it for both elements
1366
            const double local0 = Pointer((base + "/angle/0").c_str()).Get(parameters)->GetDouble();
294✔
1367
            angle = Point<2>(local0,local0,invalid);
294✔
1368
          }
1369
        else
1370
          {
1371
            const double local0 = Pointer((base + "/angle/0").c_str()).Get(parameters)->GetDouble();
300✔
1372
            const double local1 = Pointer((base + "/angle/1").c_str()).Get(parameters)->GetDouble();
300✔
1373
            angle = Point<2>(local0,local1,invalid);
300✔
1374
          }
1375

1376

1377
        // Get temperature models
1378
        std::vector<std::shared_ptr<Temperature::Interface> > temperature_models;
594✔
1379

1380
        //This is a value to look back in the path elements.
1381
        size_t searchback = 0;
594✔
1382
        if (!this->get_shared_pointers<Temperature::Interface>("temperature models", temperature_models) ||
2,636✔
1383
            Pointer((base + "/temperature model default entry").c_str()).Get(parameters) != nullptr)
854✔
1384
          {
1385
            temperature_models = default_temperature_models;
522✔
1386

1387
            // find the default value, which is the closest to the current path
1388
            for (searchback = 0; searchback < path.size(); ++searchback)
1,464✔
1389
              {
1390
                if (Pointer((this->get_full_json_path(path.size()-searchback) + "/temperature models").c_str()).Get(parameters) != nullptr)
1,420✔
1391
                  {
1392
                    break;
478✔
1393
                  }
1394
              }
1395

1396
            // if we can not find default value for the temperature model, skip it
1397
            if (searchback < path.size())
522✔
1398
              {
1399

1400
                // copy the value, this unfortunately removes it.
1401
                Value value1 = Value(Pointer((this->get_full_json_path(path.size()-searchback) + "/temperature models").c_str()).Get(parameters)->GetArray());
478✔
1402

1403
                // now copy it
1404
                Value value2;
478✔
1405
                value2.CopyFrom(value1, parameters.GetAllocator());
478✔
1406

1407
                // now we should have 2x the same value, so put it back and place it in the correct location.
1408
                Pointer((this->get_full_json_path(path.size()-searchback) + "/temperature models").c_str()).Set(parameters, value1);//.Get(parameters)->Set("temperature models", value1, parameters.GetAllocator());
478✔
1409

1410
                Pointer((base).c_str()).Get(parameters)->AddMember("temperature models", value2, parameters.GetAllocator());
478✔
1411
                Pointer((base + "/temperature model default entry").c_str()).Set(parameters,true);
478✔
1412
              }
478✔
1413
          }
1414

1415
        // now do the same for compositions
1416
        std::vector<std::shared_ptr<Composition::Interface> > composition_models;
594✔
1417
        if (!this->get_shared_pointers<Composition::Interface>("composition models", composition_models) ||
2,626✔
1418
            Pointer((base + "/composition model default entry").c_str()).Get(parameters) != nullptr)
844✔
1419
          {
1420
            composition_models = default_composition_models;
563✔
1421

1422

1423
            // find the default value, which is the closest to the current path
1424
            for (searchback = 0; searchback < path.size(); ++searchback)
1,697✔
1425
              {
1426
                if (Pointer((this->get_full_json_path(path.size()-searchback) + "/composition models").c_str()).Get(parameters) != nullptr)
1,585✔
1427
                  {
1428
                    break;
451✔
1429
                  }
1430
              }
1431

1432
            // if we can not find default value for the temperature model, skip it
1433
            if (searchback < path.size())
563✔
1434
              {
1435

1436
                // copy the value, this unfortunately removes it.
1437
                Value value1 = Value(Pointer((this->get_full_json_path(path.size()-searchback) + "/composition models").c_str()).Get(parameters)->GetArray());
451✔
1438

1439
                // now copy it
1440
                Value value2;
451✔
1441
                value2.CopyFrom(value1, parameters.GetAllocator());
451✔
1442

1443
                // now we should have 2x the same value, so put it back and place it in the correct location.
1444
                Pointer((this->get_full_json_path(path.size()-searchback) + "/composition models").c_str()).Set(parameters, value1);//.Get(parameters)->Set("temperature models", value1, parameters.GetAllocator());
451✔
1445

1446
                Pointer((base).c_str()).Get(parameters)->AddMember("composition models", value2, parameters.GetAllocator());
451✔
1447
                Pointer((base + "/composition model default entry").c_str()).Set(parameters,true);
451✔
1448
              }
451✔
1449
          }
1450

1451
        // now do the same for grains
1452
        std::vector<std::shared_ptr<Grains::Interface> > grains_models;
594✔
1453
        if (!this->get_shared_pointers<Grains::Interface>("grains models", grains_models) ||
2,454✔
1454
            Pointer((base + "/grains model default entry").c_str()).Get(parameters) != nullptr)
672✔
1455
          {
1456
            grains_models = default_grains_models;
594✔
1457

1458

1459
            // find the default value, which is the closest to the current path
1460
            for (searchback = 0; searchback < path.size(); ++searchback)
3,076✔
1461
              {
1462
                if (Pointer((this->get_full_json_path(path.size()-searchback) + "/grains models").c_str()).Get(parameters) != nullptr)
2,604✔
1463
                  {
1464
                    break;
122✔
1465
                  }
1466
              }
1467

1468
            // if we can not find default value for the temperature model, skip it
1469
            if (searchback < path.size())
594✔
1470
              {
1471

1472
                // copy the value, this unfortunately removes it.
1473
                Value value1 = Value(Pointer((this->get_full_json_path(path.size()-searchback) + "/grains models").c_str()).Get(parameters)->GetArray());
122✔
1474

1475
                // now copy it
1476
                Value value2;
122✔
1477
                value2.CopyFrom(value1, parameters.GetAllocator());
122✔
1478

1479
                // now we should have 2x the same value, so put it back and place it in the correct location.
1480
                Pointer((this->get_full_json_path(path.size()-searchback) + "/grains models").c_str()).Set(parameters, value1);//.Get(parameters)->Set("temperature models", value1, parameters.GetAllocator());
122✔
1481

1482
                Pointer((base).c_str()).Get(parameters)->AddMember("grains models", value2, parameters.GetAllocator());
122✔
1483
                Pointer((base + "/grains model default entry").c_str()).Set(parameters,true);
122✔
1484
              }
122✔
1485
          }
1486

1487
        // now do the same for velocities
1488
        std::vector<std::shared_ptr<Velocity::Interface> > velocity_models;
594✔
1489
        if (!this->get_shared_pointers<Velocity::Interface>("velocity models", velocity_models) ||
2,380✔
1490
            Pointer((base + "/velocity model default entry").c_str()).Get(parameters) != nullptr)
598✔
1491
          {
1492
            velocity_models = default_velocity_models;
590✔
1493

1494

1495
            // find the default value, which is the closest to the current path
1496
            for (searchback = 0; searchback < path.size(); ++searchback)
3,588✔
1497
              {
1498
                if (Pointer((this->get_full_json_path(path.size()-searchback) + "/velocity models").c_str()).Get(parameters) != nullptr)
3,001✔
1499
                  {
1500
                    break;
3✔
1501
                  }
1502
              }
1503

1504
            // if we can not find default value for the temperature model, skip it
1505
            if (searchback < path.size())
590✔
1506
              {
1507

1508
                // copy the value, this unfortunately removes it.
1509
                Value value1 = Value(Pointer((this->get_full_json_path(path.size()-searchback) + "/velocity models").c_str()).Get(parameters)->GetArray());
3✔
1510

1511
                // now copy it
1512
                Value value2;
3✔
1513
                value2.CopyFrom(value1, parameters.GetAllocator());
3✔
1514

1515
                // now we should have 2x the same value, so put it back and place it in the correct location.
1516
                Pointer((this->get_full_json_path(path.size()-searchback) + "/velocity models").c_str()).Set(parameters, value1);//.Get(parameters)->Set("temperature models", value1, parameters.GetAllocator());
3✔
1517

1518
                Pointer((base).c_str()).Get(parameters)->AddMember("velocity models", value2, parameters.GetAllocator());
3✔
1519
                Pointer((base + "/velocity model default entry").c_str()).Set(parameters,true);
3✔
1520
              }
3✔
1521
          }
1522
        vector.emplace_back(length, thickness, top_truncation, angle, temperature_models, composition_models, grains_models, velocity_models);
594✔
1523

1524
        this->leave_subsection();
594✔
1525
      }
594✔
1526

1527
    this->leave_subsection();
201✔
1528
    return vector;
402✔
1529
  }
201✔
1530

1531

1532
  template<>
1533
  std::vector<Objects::Segment<Features::FaultModels::Temperature::Interface,Features::FaultModels::Composition::Interface, Features::FaultModels::Grains::Interface, Features::FaultModels::Velocity::Interface> >
1534
  Parameters::get_vector(const std::string &name,
156✔
1535
                         std::vector<std::shared_ptr<Features::FaultModels::Temperature::Interface> > &default_temperature_models,
1536
                         std::vector<std::shared_ptr<Features::FaultModels::Composition::Interface> > &default_composition_models,
1537
                         std::vector<std::shared_ptr<Features::FaultModels::Grains::Interface> > &default_grains_models,
1538
                         std::vector<std::shared_ptr<Features::FaultModels::Velocity::Interface> > &default_velocity_models)
1539
  {
1540
    using namespace Features::FaultModels;
1541
    std::vector<Objects::Segment<Temperature::Interface,Composition::Interface,Grains::Interface,Velocity::Interface> > vector;
156✔
1542
    this->enter_subsection(name);
156✔
1543
    const std::string strict_base = this->get_full_json_path();
156✔
1544
    WBAssertThrow(Pointer((strict_base).c_str()).Get(parameters) != nullptr,"error: " << name
156✔
1545
                  << " was not defined in " << strict_base << ", schema path: " << this->get_full_json_schema_path() << ".");
1546

1547
    // get the array of segments
1548
    Value *array = Pointer((strict_base).c_str()).Get(parameters);
156✔
1549

1550
    for (size_t i = 0; i < array->Size(); ++i )
529✔
1551
      {
1552
        this->enter_subsection(std::to_string(i));
373✔
1553
        const std::string base = this->get_full_json_path();
373✔
1554
        // get one segment
1555
        // length
1556
        const double length = Pointer((base + "/length").c_str()).Get(parameters)->GetDouble();
373✔
1557

1558
        // get thickness
1559
        Value *point_array = Pointer((base  + "/thickness").c_str()).Get(parameters);
373✔
1560
        Point<2> thickness(invalid);
373✔
1561
        WBAssertThrow(point_array != nullptr,"error: " << name
373✔
1562
                      << " was not defined in " << strict_base << "/thickness, schema path: " << this->get_full_json_schema_path() << "/thickness.");
1563

1564
        if (point_array->Size() == 1)
373✔
1565
          {
1566
            // There is only one value, set it for both elements
1567
            const double local0 = Pointer((base + "/thickness/0").c_str()).Get(parameters)->GetDouble();
200✔
1568
            thickness = Point<2>(local0,local0,invalid);
200✔
1569
          }
1570
        else
1571
          {
1572
            const double local0 = Pointer((base + "/thickness/0").c_str()).Get(parameters)->GetDouble();
173✔
1573
            const double local1 = Pointer((base + "/thickness/1").c_str()).Get(parameters)->GetDouble();
173✔
1574
            thickness = Point<2>(local0,local1,invalid);
173✔
1575
          }
1576

1577

1578
        // get top truncation (default is 0,0)
1579
        point_array = Pointer((base  + "/top truncation").c_str()).Get(parameters);
373✔
1580
        Point<2> top_truncation(invalid);
373✔
1581
        if (point_array != nullptr)
373✔
1582
          {
1583
            if (point_array->Size() == 1)
16✔
1584
              {
1585
                // There is only one value, set it for both elements
1586
                const double local0 = Pointer((base + "/top truncation/0").c_str()).Get(parameters)->GetDouble();
8✔
1587
                top_truncation = Point<2>(local0,local0,invalid);
8✔
1588
              }
1589
            else
1590
              {
1591
                const double local0 = Pointer((base + "/top truncation/0").c_str()).Get(parameters)->GetDouble();
8✔
1592
                const double local1 = Pointer((base + "/top truncation/1").c_str()).Get(parameters)->GetDouble();
8✔
1593
                top_truncation = Point<2>(local0,local1,invalid);
8✔
1594
              }
1595
          }
1596
        // get thickness
1597
        point_array = Pointer((base  + "/angle").c_str()).Get(parameters);
373✔
1598
        Point<2> angle(invalid);
373✔
1599
        WBAssertThrow(point_array != nullptr,"error: " << name
373✔
1600
                      << " was not defined in " << strict_base << "/angle, schema path: " << this->get_full_json_schema_path() << "/angle.");
1601

1602
        if (point_array->Size() == 1)
373✔
1603
          {
1604
            // There is only one value, set it for both elements
1605
            const double local0 = Pointer((base + "/angle/0").c_str()).Get(parameters)->GetDouble();
306✔
1606
            angle = Point<2>(local0,local0,invalid);
306✔
1607
          }
1608
        else
1609
          {
1610
            const double local0 = Pointer((base + "/angle/0").c_str()).Get(parameters)->GetDouble();
67✔
1611
            const double local1 = Pointer((base + "/angle/1").c_str()).Get(parameters)->GetDouble();
67✔
1612
            angle = Point<2>(local0,local1,invalid);
67✔
1613
          }
1614

1615

1616
        // Get temperature models
1617
        std::vector<std::shared_ptr<Temperature::Interface> > temperature_models;
373✔
1618

1619
        //This is a value to look back in the path elements.
1620
        size_t searchback = 0;
373✔
1621
        if (!this->get_shared_pointers<Temperature::Interface>("temperature models", temperature_models) ||
1,617✔
1622
            Pointer((base + "/temperature model default entry").c_str()).Get(parameters) != nullptr)
498✔
1623
          {
1624
            temperature_models = default_temperature_models;
336✔
1625

1626
            // find the default value, which is the closest to the current path
1627
            for (searchback = 0; searchback < path.size(); ++searchback)
1,462✔
1628
              {
1629
                if (Pointer((this->get_full_json_path(path.size()-searchback) + "/temperature models").c_str()).Get(parameters) != nullptr)
1,296✔
1630
                  {
1631
                    break;
170✔
1632
                  }
1633
              }
1634

1635
            // if we can not find default value for the temperature model, skip it
1636
            if (searchback < path.size())
336✔
1637
              {
1638

1639
                // copy the value, this unfortunately removes it.
1640
                Value value1 = Value(Pointer((this->get_full_json_path(path.size()-searchback) + "/temperature models").c_str()).Get(parameters)->GetArray());
170✔
1641

1642
                // now copy it
1643
                Value value2;
170✔
1644
                value2.CopyFrom(value1, parameters.GetAllocator());
170✔
1645

1646
                // now we should have 2x the same value, so put it back and place it in the correct location.
1647
                Pointer((this->get_full_json_path(path.size()-searchback) + "/temperature models").c_str()).Set(parameters, value1);//.Get(parameters)->Set("temperature models", value1, parameters.GetAllocator());
170✔
1648

1649
                Pointer((base).c_str()).Get(parameters)->AddMember("temperature models", value2, parameters.GetAllocator());
170✔
1650
                Pointer((base + "/temperature model default entry").c_str()).Set(parameters,true);
170✔
1651
              }
170✔
1652
          }
1653

1654
        // now do the same for compositions
1655
        std::vector<std::shared_ptr<Composition::Interface> > composition_models;
373✔
1656
        if (!this->get_shared_pointers<Composition::Interface>("composition models", composition_models) ||
1,602✔
1657
            Pointer((base + "/composition model default entry").c_str()).Get(parameters) != nullptr)
483✔
1658
          {
1659
            composition_models = default_composition_models;
367✔
1660

1661

1662
            // find the default value, which is the closest to the current path
1663
            for (searchback = 0; searchback < path.size(); ++searchback)
1,505✔
1664
              {
1665
                if (Pointer((this->get_full_json_path(path.size()-searchback) + "/composition models").c_str()).Get(parameters) != nullptr)
1,364✔
1666
                  {
1667
                    break;
226✔
1668
                  }
1669
              }
1670

1671
            // if we can not find default value for the temperature model, skip it
1672
            if (searchback < path.size())
367✔
1673
              {
1674

1675
                // copy the value, this unfortunately removes it.
1676
                Value value1 = Value(Pointer((this->get_full_json_path(path.size()-searchback) + "/composition models").c_str()).Get(parameters)->GetArray());
226✔
1677

1678
                // now copy it
1679
                Value value2;
226✔
1680
                value2.CopyFrom(value1, parameters.GetAllocator());
226✔
1681

1682
                // now we should have 2x the same value, so put it back and place it in the correct location.
1683
                Pointer((this->get_full_json_path(path.size()-searchback) + "/composition models").c_str()).Set(parameters, value1);//.Get(parameters)->Set("temperature models", value1, parameters.GetAllocator());
226✔
1684

1685
                Pointer((base).c_str()).Get(parameters)->AddMember("composition models", value2, parameters.GetAllocator());
226✔
1686
                Pointer((base + "/composition model default entry").c_str()).Set(parameters,true);
226✔
1687
              }
226✔
1688
          }
1689

1690
        // now do the same for grains
1691
        std::vector<std::shared_ptr<Grains::Interface> > grains_models;
373✔
1692
        if (!this->get_shared_pointers<Grains::Interface>("grains models", grains_models) ||
1,578✔
1693
            Pointer((base + "/grains model default entry").c_str()).Get(parameters) != nullptr)
459✔
1694
          {
1695
            grains_models = default_grains_models;
365✔
1696

1697

1698
            // find the default value, which is the closest to the current path
1699
            for (searchback = 0; searchback < path.size(); ++searchback)
1,779✔
1700
              {
1701
                if (Pointer((this->get_full_json_path(path.size()-searchback) + "/grains models").c_str()).Get(parameters) != nullptr)
1,546✔
1702
                  {
1703
                    break;
132✔
1704
                  }
1705
              }
1706

1707
            // if we can not find default value for the temperature model, skip it
1708
            if (searchback < path.size())
365✔
1709
              {
1710

1711
                // copy the value, this unfortunately removes it.
1712
                Value value1 = Value(Pointer((this->get_full_json_path(path.size()-searchback) + "/grains models").c_str()).Get(parameters)->GetArray());
132✔
1713

1714
                // now copy it
1715
                Value value2;
132✔
1716
                value2.CopyFrom(value1, parameters.GetAllocator());
132✔
1717

1718
                // now we should have 2x the same value, so put it back and place it in the correct location.
1719
                Pointer((this->get_full_json_path(path.size()-searchback) + "/grains models").c_str()).Set(parameters, value1);//.Get(parameters)->Set("temperature models", value1, parameters.GetAllocator());
132✔
1720

1721
                Pointer((base).c_str()).Get(parameters)->AddMember("grains models", value2, parameters.GetAllocator());
132✔
1722
                Pointer((base + "/grains model default entry").c_str()).Set(parameters,true);
132✔
1723
              }
132✔
1724
          }
1725

1726
        // now do the same for velocitys
1727
        std::vector<std::shared_ptr<Velocity::Interface> > velocity_models;
373✔
1728
        if (!this->get_shared_pointers<Velocity::Interface>("velocity models", velocity_models) ||
1,496✔
1729
            Pointer((base + "/velocity model default entry").c_str()).Get(parameters) != nullptr)
377✔
1730
          {
1731
            velocity_models = default_velocity_models;
369✔
1732

1733

1734
            // find the default value, which is the closest to the current path
1735
            for (searchback = 0; searchback < path.size(); ++searchback)
2,383✔
1736
              {
1737
                if (Pointer((this->get_full_json_path(path.size()-searchback) + "/velocity models").c_str()).Get(parameters) != nullptr)
2,015✔
1738
                  {
1739
                    break;
1✔
1740
                  }
1741
              }
1742

1743
            // if we can not find default value for the temperature model, skip it
1744
            if (searchback < path.size())
369✔
1745
              {
1746

1747
                // copy the value, this unfortunately removes it.
1748
                Value value1 = Value(Pointer((this->get_full_json_path(path.size()-searchback) + "/velocity models").c_str()).Get(parameters)->GetArray());
1✔
1749

1750
                // now copy it
1751
                Value value2;
1✔
1752
                value2.CopyFrom(value1, parameters.GetAllocator());
1✔
1753

1754
                // now we should have 2x the same value, so put it back and place it in the correct location.
1755
                Pointer((this->get_full_json_path(path.size()-searchback) + "/velocity models").c_str()).Set(parameters, value1);//.Get(parameters)->Set("temperature models", value1, parameters.GetAllocator());
1✔
1756

1757
                Pointer((base).c_str()).Get(parameters)->AddMember("velocity models", value2, parameters.GetAllocator());
1✔
1758
                Pointer((base + "/velocity model default entry").c_str()).Set(parameters,true);
1✔
1759
              }
1✔
1760
          }
1761

1762
        vector.emplace_back(length, thickness, top_truncation, angle, temperature_models, composition_models, grains_models, velocity_models);
373✔
1763

1764
        this->leave_subsection();
373✔
1765
      }
373✔
1766

1767
    this->leave_subsection();
156✔
1768
    return vector;
312✔
1769
  }
156✔
1770

1771
  template<>
1772
  std::vector<double>
1773
  Parameters::get_vector(const std::string &name)
2,155✔
1774
  {
1775
    std::vector<double> vector;
2,155✔
1776
    const std::string strict_base = this->get_full_json_path();
2,155✔
1777
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
2,155✔
1778
      {
1779
        Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
1,077✔
1780

1781
        for (size_t i = 0; i < array->Size(); ++i )
3,412✔
1782
          {
1783
            const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
2,335✔
1784

1785
            vector.push_back(Pointer(base.c_str()).Get(parameters)->GetDouble());
2,335✔
1786
          }
2,335✔
1787
      }
1788
    else
1789
      {
1790
        const Value *value = Pointer((this->get_full_json_schema_path()  + "/" + name + "/minItems").c_str()).Get(declarations);
1,078✔
1791
        WBAssertThrow(value != nullptr,
1,078✔
1792
                      "internal error: could not retrieve the minItems value at: "
1793
                      << this->get_full_json_schema_path() + "/" + name + "/minItems");
1794

1795
        const size_t min_size = value->GetUint();
1,077✔
1796

1797
        value = Pointer((this->get_full_json_schema_path()  + "/" + name + "/items/default value").c_str()).Get(declarations);
1,077✔
1798
        WBAssertThrow(value != nullptr,
1,077✔
1799
                      "internal error: could not retrieve the default value at: "
1800
                      << this->get_full_json_schema_path() + "/" + name + "/default value");
1801

1802
        const double default_value = value->GetDouble();
1,077✔
1803

1804
        // set to min size
1805
        for (size_t i = 0; i < min_size; ++i)
2,155✔
1806
          {
1807
            vector.push_back(default_value);
1,078✔
1808
          }
1809
      }
1810
    return vector;
4,308✔
1811
  }
2,156✔
1812

1813
  template<>
1814
  std::vector<size_t>
1815
  Parameters::get_vector(const std::string &name)
4✔
1816
  {
1817
    std::vector<size_t> vector;
4✔
1818
    const std::string strict_base = this->get_full_json_path();
4✔
1819
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
4✔
1820
      {
1821
        Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
1✔
1822

1823
        for (size_t i = 0; i < array->Size(); ++i )
4✔
1824
          {
1825
            const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
3✔
1826

1827
            vector.push_back(Pointer(base.c_str()).Get(parameters)->GetUint());
3✔
1828
          }
3✔
1829
      }
1830
    else
1831
      {
1832
        const Value *value = Pointer((this->get_full_json_schema_path()  + "/" + name + "/minItems").c_str()).Get(declarations);
3✔
1833
        WBAssertThrow(value != nullptr,
3✔
1834
                      "internal error: could not retrieve the minItems value at: "
1835
                      << this->get_full_json_schema_path() + "/" + name + "/minItems");
1836

1837
        const size_t min_size = value->GetUint();
1✔
1838

1839
        value = Pointer((this->get_full_json_schema_path()  + "/" + name + "/items/default value").c_str()).Get(declarations);
1✔
1840
        WBAssertThrow(value != nullptr,
1✔
1841
                      "internal error: could not retrieve the default value at: "
1842
                      << this->get_full_json_schema_path() + "/" + name + "/default value");
1843

1844
        const size_t default_value = value->GetUint();
1✔
1845

1846
        // set to min size
1847
        for (size_t i = 0; i < min_size; ++i)
3✔
1848
          {
1849
            vector.push_back(default_value);
2✔
1850
          }
1851
      }
1852
    return vector;
4✔
1853
  }
6✔
1854

1855
  template<>
1856
  std::vector<unsigned int>
1857
  Parameters::get_vector(const std::string &name)
2,052✔
1858
  {
1859
    std::vector<unsigned int> vector;
2,052✔
1860
    const std::string strict_base = this->get_full_json_path();
2,052✔
1861
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
2,052✔
1862
      {
1863
        Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
2,050✔
1864

1865
        for (size_t i = 0; i < array->Size(); ++i )
4,938✔
1866
          {
1867
            const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
2,888✔
1868

1869
            vector.push_back(Pointer(base.c_str()).Get(parameters)->GetUint());
2,888✔
1870
          }
2,888✔
1871
      }
1872
    else
1873
      {
1874
        const Value *value = Pointer((this->get_full_json_schema_path()  + "/" + name + "/minItems").c_str()).Get(declarations);
2✔
1875
        WBAssertThrow(value != nullptr,
2✔
1876
                      "internal error: could not retrieve the minItems value at: "
1877
                      << this->get_full_json_schema_path() + "/" + name + "/minItems value");
1878

1879
        const size_t min_size = value->GetUint();
1✔
1880

1881
        const unsigned int default_value = Pointer((this->get_full_json_schema_path()  + "/" + name + "/items/default value").c_str()).Get(declarations)->GetUint();
1✔
1882

1883
        // set to min size
1884
        for (size_t i = 0; i < min_size; ++i)
3✔
1885
          {
1886
            vector.push_back(default_value);
2✔
1887
          }
1888
      }
1889
    return vector;
4,102✔
1890
  }
2,053✔
1891

1892
  template<class T>
1893
  std::unique_ptr<T>
1894
  Parameters::get_unique_pointer(const std::string &name)
304✔
1895
  {
1896
    const std::string base = this->get_full_json_path();
304✔
1897
    Value *value = Pointer((base + "/" + name + "/model").c_str()).Get(parameters);
304✔
1898

1899
#ifdef debug
1900
    bool required = false;
1901
    if (Pointer((base + "/required").c_str()).Get(declarations) != NULL)
1902
      for (auto &v : Pointer((base + "/required").c_str()).Get(declarations)->GetArray())
1903
        {
1904
          if (v.GetString() == name)
1905
            {
1906
              required = true;
1907
            }
1908
        }
1909

1910
    WBAssert(value != NULL || required == false,
1911
             "Internal error: Value \"" << base << '/' << name << "/model\" not found in the input file, while it was set as required.");
1912
#endif
1913
    if (value == nullptr)
304✔
1914
      {
1915
        value = Pointer((get_full_json_schema_path() + "/" + name + "/default value").c_str()).Get(declarations);
106✔
1916
        WBAssertThrow(value != nullptr,
106✔
1917
                      "internal error: could not retrieve the default value at: "
1918
                      << base + "/" + name + "/default value. Make sure the value has been declared.");
1919
      }
1920

1921
    return T::create(value->GetString(),&world);
912✔
1922
  }
304✔
1923

1924
  template<class T>
1925
  bool
1926
  Parameters::get_unique_pointers(const std::string &name, std::vector<std::unique_ptr<T> > &vector)
1,488✔
1927
  {
1928
    vector.resize(0);
1,488✔
1929
    const std::string strict_base = this->get_full_json_path();
1,488✔
1930
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
1,488✔
1931
      {
1932
        Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
815✔
1933

1934
        for (size_t i = 0; i < array->Size(); ++i )
2,157✔
1935
          {
1936
            const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
1,342✔
1937

1938
            const std::string value = Pointer((base + "/model").c_str()).Get(parameters)->GetString();
1,342✔
1939

1940
            vector.push_back(std::move(T::create(value, &world)));
1,342✔
1941
          }
1942
      }
1943
    else
1944
      {
1945
        return false;
673✔
1946
      }
1947

1948
    return true;
815✔
1949
  }
1,488✔
1950

1951
  template<>
1952
  bool
1953
  Parameters::get_unique_pointers(const std::string &name, std::vector<std::unique_ptr<Features::SubductingPlate> > &vector)
89✔
1954
  {
1955
    vector.resize(0);
89✔
1956
    const std::string strict_base = this->get_full_json_path();
89✔
1957
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
89✔
1958
      {
1959
        Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
20✔
1960

1961
        for (size_t i = 0; i < array->Size(); ++i )
53✔
1962
          {
1963
            vector.push_back(std::make_unique<Features::SubductingPlate>(&world));
33✔
1964
          }
1965
      }
1966
    else
1967
      {
1968
        return false;
69✔
1969
      }
1970

1971
    return true;
20✔
1972
  }
89✔
1973

1974
  template<>
1975
  bool
1976
  Parameters::get_unique_pointers(const std::string &name, std::vector<std::unique_ptr<Features::Fault> > &vector)
63✔
1977
  {
1978
    vector.resize(0);
63✔
1979
    const std::string strict_base = this->get_full_json_path();
63✔
1980
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
63✔
1981
      {
1982
        Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
16✔
1983

1984
        for (size_t i = 0; i < array->Size(); ++i )
46✔
1985
          {
1986
            vector.push_back(std::make_unique<Features::Fault>(&world));
30✔
1987
          }
1988
      }
1989
    else
1990
      {
1991
        return false;
47✔
1992
      }
1993

1994
    return true;
16✔
1995
  }
63✔
1996

1997

1998

1999
  template<class T>
2000
  bool
2001
  Parameters::get_shared_pointers(const std::string &name, std::vector<std::shared_ptr<T> > &vector)
5,296✔
2002
  {
2003
    vector.resize(0);
5,296✔
2004
    const std::string strict_base = this->get_full_json_path();
5,296✔
2005
    if (Pointer((strict_base + "/" + name).c_str()).Get(parameters) != nullptr)
5,296✔
2006
      {
2007
        Value *array = Pointer((strict_base  + "/" + name).c_str()).Get(parameters);
1,175✔
2008

2009
        for (size_t i = 0; i < array->Size(); ++i )
2,851✔
2010
          {
2011
            const std::string base = (strict_base + "/").append(name).append("/").append(std::to_string(i));
1,676✔
2012

2013
            const std::string value = Pointer((base + "/model").c_str()).Get(parameters)->GetString();
1,676✔
2014

2015
            vector.push_back(std::move(T::create(value, &world)));
1,676✔
2016
          }
2017
      }
2018
    else
2019
      {
2020
        return false;
4,121✔
2021
      }
2022

2023
    return true;
1,175✔
2024
  }
5,296✔
2025

2026
  void
2027
  Parameters::enter_subsection(const std::string &name)
224,535✔
2028
  {
2029
    path.push_back(name);
224,535✔
2030
    //TODO: WBAssert(is path valid?)
2031
  }
224,535✔
2032

2033
  void
2034
  Parameters::leave_subsection()
224,535✔
2035
  {
2036
    path.pop_back();
224,535✔
2037
  }
224,535✔
2038

2039

2040

2041
  void
2042
  Parameters::declare_model_entries(const std::string &model_group_name,
5,776✔
2043
                                    const std::string &parent_name,
2044
                                    const std::map<std::string, void ( *)(Parameters &,const std::string &)> &declare_map,
2045
                                    const std::vector<std::string> &required_entries,
2046
                                    const std::vector<std::tuple<std::string,const WorldBuilder::Types::Interface &, std::string> > &extra_declarations)
2047
  {
2048
    unsigned int counter = 0;
5,776✔
2049
    for (const auto &it : declare_map)
19,456✔
2050
      {
2051
        typedef std::tuple<std::string,const WorldBuilder::Types::Interface &, std::string> DeclareEntry;
2052
        // prevent infinite recursion
2053
        if (it.first != parent_name)
13,680✔
2054
          {
2055
            enter_subsection("oneOf");
13,680✔
2056
            {
2057
              enter_subsection(std::to_string(counter));
13,680✔
2058
              {
2059
                enter_subsection("properties");
13,680✔
2060
                {
2061
                  declare_entry("", Types::Object(required_entries), model_group_name + " object");
41,040✔
2062

2063
                  declare_entry("model", Types::String("",it.first),
54,720✔
2064
                                "The name of the " + model_group_name + " model.");
27,360✔
2065

2066
                  for (DeclareEntry extra_declaration : extra_declarations)
22,648✔
2067
                    {
2068
                      declare_entry(std::get<0>(extra_declaration),std::get<1>(extra_declaration),std::get<2>(extra_declaration));
8,968✔
2069
                    }
8,968✔
2070

2071

2072
                  it.second(*this, parent_name);
13,680✔
2073
                }
2074
                leave_subsection();
13,680✔
2075
              }
2076
              leave_subsection();
13,680✔
2077
            }
2078
            leave_subsection();
13,680✔
2079

2080
            counter++;
13,680✔
2081

2082
          }
2083
      }
2084
  }
5,776✔
2085

2086

2087

2088
  std::string
2089
  Parameters::get_full_json_path(size_t max_size) const
525,136✔
2090
  {
2091
    std::string collapse;
525,136✔
2092
    for (size_t i = 0; i < path.size() && i < max_size; i++)
5,097,051✔
2093
      {
2094
        collapse +=  "/" + path[i];
4,571,915✔
2095
      }
2096
    return collapse;
525,136✔
2097
  }
×
2098

2099
  std::string
2100
  Parameters::get_full_json_schema_path() const
15,548✔
2101
  {
2102
    std::string collapse = "/properties";
15,548✔
2103
    for (size_t i = 0; i < path.size(); i++)
69,902✔
2104
      {
2105
        // first get the type
2106
        //WBAssert(Pointer((collapse + "/" + path[i] + "/type").c_str()).Get(declarations) != NULL, "Internal error: could not find " << collapse + "/" + path[i] + "/type");
2107

2108
        const std::string base_path = Pointer((collapse + "/" + path[i] + "/type").c_str()).Get(declarations) != nullptr
108,708✔
2109
                                      ?
54,354✔
2110
                                      collapse + "/" + path[i]
94,675✔
2111
                                      :
2112
                                      collapse;
94,675✔
2113

2114
        const std::string type = Pointer((base_path + "/type").c_str()).Get(declarations)->GetString();
54,354✔
2115

2116
        if (type == "array")
54,354✔
2117
          {
2118
            // the type is an array. Arrays always have an items, but can also
2119
            // have a oneOf (todo: or anyOf ...). Find out whether this is the case
2120
            //collapse += path[i] + "/items";
2121
            if (Pointer((base_path + "/items/oneOf").c_str()).Get(declarations) != nullptr)
40,209✔
2122
              {
2123
                // it has a structure with oneOf. Find out which of the entries is needed.
2124
                // This means we have to take a sneak peak to figure out how to get to the
2125
                // next value.
2126
                const size_t size = Pointer((base_path + "/items/oneOf").c_str()).Get(declarations)->Size();
26,176✔
2127
#ifdef debug
2128
                bool found = false;
2129
#endif
2130
                size_t index = 0;
26,176✔
2131
                for (; index < size; ++index)
91,962✔
2132
                  {
2133
                    const std::string declarations_string = Pointer((base_path + "/items/oneOf/" + std::to_string(index)
367,848✔
2134
                                                                     + "/properties/model/enum/0").c_str()).Get(declarations)->GetString();
367,848✔
2135

2136
                    // we need to get the json path relevant for the current declaration string
2137
                    // we are interested in, which requires an offset of 2.
2138
                    WBAssert(Pointer((get_full_json_path(i+2) + "/model").c_str()).Get(parameters) != nullptr, "Could not find model in: " << get_full_json_path(i+2) + "/model");
91,962✔
2139
                    const std::string parameters_string = Pointer((get_full_json_path(i+2) + "/model").c_str()).Get(parameters)->GetString();
91,962✔
2140

2141
                    // currently in our case these are always objects, so go directly to find the option we need.
2142
                    if (declarations_string == parameters_string)
91,962✔
2143
                      {
2144
                        // found it for index i;
2145
#ifdef debug
2146
                        found = true;
2147
#endif
2148
                        break;
26,176✔
2149
                      }
2150
                  }
118,138✔
2151
#ifdef debug
2152
                WBAssert(found == true,
2153
                         "Internal error: This is an array with several possible values, "
2154
                         "but could not find the correct value " << collapse + "/" + path[i] + "/items/oneOf");
2155
#endif
2156
                collapse += "/" + path[i] + "/items/oneOf/" + std::to_string(index) + "/properties";
26,176✔
2157
                // add one to i, to skip the array
2158
                ++i;
26,176✔
2159
              }
2160
            else
2161
              {
2162
                collapse = base_path + "/items";
14,033✔
2163
              }
2164
          }
2165
        else if (type == "object")
14,145✔
2166
          {
2167
            // normal objects just have properties, but some have oneOf
2168
            if (Pointer((base_path + "/oneOf").c_str()).Get(declarations) != nullptr)
14,145✔
2169
              {
2170
                // it has a structure with oneOf. Find out which of the entries is needed.
2171
                // This means we have to take a sneak peak to figure out how to get to the
2172
                // next value.
2173
                const size_t size = Pointer((base_path + "/oneOf").c_str()).Get(declarations)->Size();
112✔
2174
#ifdef debug
2175
                bool found = false;
2176
#endif
2177
                size_t index = 0;
112✔
2178
                for (; index < size; ++index)
151✔
2179
                  {
2180
                    const std::string declarations_string = Pointer((base_path + "/oneOf/" + std::to_string(index)
604✔
2181
                                                                     + "/properties/model/enum/0").c_str()).Get(declarations)->GetString();
604✔
2182

2183
                    // we need to get the json path relevant for the current declaration string
2184
                    // we are interested in, which requires an offset of 2.
2185
                    const Value *value = Pointer((get_full_json_path(i+2) + "/model").c_str()).Get(parameters);
151✔
2186

2187

2188
                    if (value == nullptr)
151✔
2189
                      {
2190
                        value = Pointer((collapse + "/" + path[i]  + "/default value").c_str()).Get(declarations);
73✔
2191
                        WBAssertThrow(value != nullptr,
73✔
2192
                                      "internal error: could not retrieve the default value at: "
2193
                                      << collapse + "/" + path[i]  + "/default value, for value: ");
2194
                      }
2195

2196
                    const std::string parameters_string = value->GetString();
151✔
2197

2198
                    // currently in our case these are always objects, so go directly to find the option we need.
2199
                    if (declarations_string == parameters_string)
151✔
2200
                      {
2201
                        // found it for index i;
2202
#ifdef debug
2203
                        found = true;
2204
#endif
2205
                        break;
112✔
2206
                      }
2207
                  }
263✔
2208
#ifdef debug
2209
                WBAssert(found == true,
2210
                         "Internal error: This is an array with several possible values, "
2211
                         "but could not find the correct value " << collapse + "/" + path[i] + "/items/oneOf");
2212
#endif
2213
                collapse += "/" + path[i] + "/oneOf/" + std::to_string(index) + "/properties";
112✔
2214
                // add one to i, to skip the array
2215
                ++i;
112✔
2216

2217
              }
2218
            else
2219
              {
2220
                collapse += "/properties";
14,033✔
2221
              }
2222
          }
2223
        else
2224
          {
2225
            collapse += "/" + path[i];
×
2226
          }
2227
      }
54,354✔
2228
    return collapse;
15,548✔
2229
  }
×
2230

2231

2232

2233

2234

2235
  /**
2236
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2237
   * Note that the variable with this name has to be loaded before this function is called.
2238
   */
2239
  template std::unique_ptr<CoordinateSystems::Interface> Parameters::get_unique_pointer<CoordinateSystems::Interface>(const std::string &name);
2240

2241

2242
  /**
2243
   * Returns a vector of pointers to the Gravity Model based on the provided name.
2244
   * Note that the variable with this name has to be loaded before this function is called.
2245
   */
2246
  template std::unique_ptr<GravityModel::Interface> Parameters::get_unique_pointer<GravityModel::Interface>(const std::string &name);
2247

2248

2249

2250
  /**
2251
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2252
   * Note that the variable with this name has to be loaded before this function is called.
2253
   */
2254
  template bool
2255
  Parameters::get_unique_pointers<Features::Interface>(const std::string &name,
2256
                                                       std::vector<std::unique_ptr<Features::Interface> > &vector);
2257

2258

2259
  /**
2260
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2261
   * Note that the variable with this name has to be loaded before this function is called.
2262
   */
2263
  template bool
2264
  Parameters::get_unique_pointers<Features::ContinentalPlateModels::Temperature::Interface>(const std::string &name,
2265
      std::vector<std::unique_ptr<Features::ContinentalPlateModels::Temperature::Interface> > &vector);
2266

2267
  /**
2268
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2269
  * Note that the variable with this name has to be loaded before this function is called.
2270
  */
2271
  template bool
2272
  Parameters::get_unique_pointers<Features::ContinentalPlateModels::Composition::Interface>(const std::string &name,
2273
      std::vector<std::unique_ptr<Features::ContinentalPlateModels::Composition::Interface> > &vector);
2274

2275
  /**
2276
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2277
  * Note that the variable with this name has to be loaded before this function is called.
2278
  */
2279
  template bool
2280
  Parameters::get_unique_pointers<Features::ContinentalPlateModels::Grains::Interface>(const std::string &name,
2281
      std::vector<std::unique_ptr<Features::ContinentalPlateModels::Grains::Interface> > &vector);
2282

2283
  /**
2284
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2285
  * Note that the variable with this name has to be loaded before this function is called.
2286
  */
2287
  template bool
2288
  Parameters::get_unique_pointers<Features::ContinentalPlateModels::Velocity::Interface>(const std::string &name,
2289
      std::vector<std::unique_ptr<Features::ContinentalPlateModels::Velocity::Interface> > &vector);
2290

2291

2292
  /**
2293
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2294
   * Note that the variable with this name has to be loaded before this function is called.
2295
   */
2296
  template bool
2297
  Parameters::get_unique_pointers<Features::PlumeModels::Temperature::Interface>(const std::string &name,
2298
                                                                                 std::vector<std::unique_ptr<Features::PlumeModels::Temperature::Interface> > &vector);
2299

2300
  /**
2301
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2302
  * Note that the variable with this name has to be loaded before this function is called.
2303
  */
2304
  template bool
2305
  Parameters::get_unique_pointers<Features::PlumeModels::Composition::Interface>(const std::string &name,
2306
                                                                                 std::vector<std::unique_ptr<Features::PlumeModels::Composition::Interface> > &vector);
2307

2308
  /**
2309
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2310
  * Note that the variable with this name has to be loaded before this function is called.
2311
  */
2312
  template bool
2313
  Parameters::get_unique_pointers<Features::PlumeModels::Grains::Interface>(const std::string &name,
2314
                                                                            std::vector<std::unique_ptr<Features::PlumeModels::Grains::Interface> > &vector);
2315

2316
  /**
2317
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2318
  * Note that the variable with this name has to be loaded before this function is called.
2319
  */
2320
  template bool
2321
  Parameters::get_unique_pointers<Features::PlumeModels::Velocity::Interface>(const std::string &name,
2322
                                                                              std::vector<std::unique_ptr<Features::PlumeModels::Velocity::Interface> > &vector);
2323

2324

2325

2326
  /**
2327
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2328
   * Note that the variable with this name has to be loaded before this function is called.
2329
   */
2330
  template bool
2331
  Parameters::get_unique_pointers<Features::OceanicPlateModels::Temperature::Interface>(const std::string &name,
2332
      std::vector<std::unique_ptr<Features::OceanicPlateModels::Temperature::Interface> > &vector);
2333

2334
  /**
2335
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2336
  * Note that the variable with this name has to be loaded before this function is called.
2337
  */
2338
  template bool
2339
  Parameters::get_unique_pointers<Features::OceanicPlateModels::Composition::Interface>(const std::string &name,
2340
      std::vector<std::unique_ptr<Features::OceanicPlateModels::Composition::Interface> > &vector);
2341

2342
  /**
2343
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2344
  * Note that the variable with this name has to be loaded before this function is called.
2345
  */
2346
  template bool
2347
  Parameters::get_unique_pointers<Features::OceanicPlateModels::Grains::Interface>(const std::string &name,
2348
      std::vector<std::unique_ptr<Features::OceanicPlateModels::Grains::Interface> > &vector);
2349

2350
  /**
2351
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2352
  * Note that the variable with this name has to be loaded before this function is called.
2353
  */
2354
  template bool
2355
  Parameters::get_unique_pointers<Features::OceanicPlateModels::Velocity::Interface>(const std::string &name,
2356
      std::vector<std::unique_ptr<Features::OceanicPlateModels::Velocity::Interface> > &vector);
2357

2358

2359

2360
  /**
2361
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2362
   * Note that the variable with this name has to be loaded before this function is called.
2363
   */
2364
  template bool
2365
  Parameters::get_unique_pointers<Features::MantleLayerModels::Temperature::Interface>(const std::string &name,
2366
      std::vector<std::unique_ptr<Features::MantleLayerModels::Temperature::Interface> > &vector);
2367

2368
  /**
2369
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2370
  * Note that the variable with this name has to be loaded before this function is called.
2371
  */
2372
  template bool
2373
  Parameters::get_unique_pointers<Features::MantleLayerModels::Composition::Interface>(const std::string &name,
2374
      std::vector<std::unique_ptr<Features::MantleLayerModels::Composition::Interface> > &vector);
2375

2376
  /**
2377
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2378
  * Note that the variable with this name has to be loaded before this function is called.
2379
  */
2380
  template bool
2381
  Parameters::get_unique_pointers<Features::MantleLayerModels::Grains::Interface>(const std::string &name,
2382
                                                                                  std::vector<std::unique_ptr<Features::MantleLayerModels::Grains::Interface> > &vector);
2383

2384
  /**
2385
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2386
  * Note that the variable with this name has to be loaded before this function is called.
2387
  */
2388
  template bool
2389
  Parameters::get_unique_pointers<Features::MantleLayerModels::Velocity::Interface>(const std::string &name,
2390
      std::vector<std::unique_ptr<Features::MantleLayerModels::Velocity::Interface> > &vector);
2391

2392

2393

2394
  /**
2395
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2396
   * Note that the variable with this name has to be loaded before this function is called.
2397
   */
2398
  template bool
2399
  Parameters::get_unique_pointers<Features::SubductingPlateModels::Temperature::Interface>(const std::string &name,
2400
      std::vector<std::unique_ptr<Features::SubductingPlateModels::Temperature::Interface> > &vector);
2401

2402
  /**
2403
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2404
  * Note that the variable with this name has to be loaded before this function is called.
2405
  */
2406
  template bool
2407
  Parameters::get_unique_pointers<Features::SubductingPlateModels::Composition::Interface>(const std::string &name,
2408
      std::vector<std::unique_ptr<Features::SubductingPlateModels::Composition::Interface> > &vector);
2409

2410
  /**
2411
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2412
  * Note that the variable with this name has to be loaded before this function is called.
2413
  */
2414
  template bool
2415
  Parameters::get_unique_pointers<Features::SubductingPlateModels::Grains::Interface>(const std::string &name,
2416
      std::vector<std::unique_ptr<Features::SubductingPlateModels::Grains::Interface> > &vector);
2417

2418
  /**
2419
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2420
  * Note that the variable with this name has to be loaded before this function is called.
2421
  */
2422
  template bool
2423
  Parameters::get_unique_pointers<Features::SubductingPlateModels::Velocity::Interface>(const std::string &name,
2424
      std::vector<std::unique_ptr<Features::SubductingPlateModels::Velocity::Interface> > &vector);
2425

2426

2427

2428
  /**
2429
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2430
   * Note that the variable with this name has to be loaded before this function is called.
2431
   */
2432
  template bool
2433
  Parameters::get_unique_pointers<Features::FaultModels::Temperature::Interface>(const std::string &name,
2434
                                                                                 std::vector<std::unique_ptr<Features::FaultModels::Temperature::Interface> > &vector);
2435

2436
  /**
2437
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2438
  * Note that the variable with this name has to be loaded before this function is called.
2439
  */
2440
  template bool
2441
  Parameters::get_unique_pointers<Features::FaultModels::Composition::Interface>(const std::string &name,
2442
                                                                                 std::vector<std::unique_ptr<Features::FaultModels::Composition::Interface> > &vector);
2443
  /**
2444
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2445
  * Note that the variable with this name has to be loaded before this function is called.
2446
  */
2447
  template bool
2448
  Parameters::get_unique_pointers<Features::FaultModels::Grains::Interface>(const std::string &name,
2449
                                                                            std::vector<std::unique_ptr<Features::FaultModels::Grains::Interface> > &vector);
2450
  /**
2451
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2452
  * Note that the variable with this name has to be loaded before this function is called.
2453
  */
2454
  template bool
2455
  Parameters::get_unique_pointers<Features::FaultModels::Velocity::Interface>(const std::string &name,
2456
                                                                              std::vector<std::unique_ptr<Features::FaultModels::Velocity::Interface> > &vector);
2457

2458

2459

2460
  /**
2461
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2462
   * Note that the variable with this name has to be loaded before this function is called.
2463
   */
2464
  template bool
2465
  Parameters::get_shared_pointers<Features::SubductingPlateModels::Temperature::Interface>(const std::string &name,
2466
      std::vector<std::shared_ptr<Features::SubductingPlateModels::Temperature::Interface> > &vector);
2467

2468
  /**
2469
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2470
  * Note that the variable with this name has to be loaded before this function is called.
2471
  */
2472
  template bool
2473
  Parameters::get_shared_pointers<Features::SubductingPlateModels::Composition::Interface>(const std::string &name,
2474
      std::vector<std::shared_ptr<Features::SubductingPlateModels::Composition::Interface> > &vector);
2475

2476
  /**
2477
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2478
  * Note that the variable with this name has to be loaded before this function is called.
2479
  */
2480
  template bool
2481
  Parameters::get_shared_pointers<Features::SubductingPlateModels::Grains::Interface>(const std::string &name,
2482
      std::vector<std::shared_ptr<Features::SubductingPlateModels::Grains::Interface> > &vector);
2483

2484
  /**
2485
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2486
  * Note that the variable with this name has to be loaded before this function is called.
2487
  */
2488
  template bool
2489
  Parameters::get_shared_pointers<Features::SubductingPlateModels::Velocity::Interface>(const std::string &name,
2490
      std::vector<std::shared_ptr<Features::SubductingPlateModels::Velocity::Interface> > &vector);
2491

2492

2493
  /**
2494
   * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2495
   * Note that the variable with this name has to be loaded before this function is called.
2496
   */
2497
  template bool
2498
  Parameters::get_shared_pointers<Features::FaultModels::Temperature::Interface>(const std::string &name,
2499
                                                                                 std::vector<std::shared_ptr<Features::FaultModels::Temperature::Interface> > &vector);
2500

2501
  /**
2502
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2503
  * Note that the variable with this name has to be loaded before this function is called.
2504
  */
2505
  template bool
2506
  Parameters::get_shared_pointers<Features::FaultModels::Composition::Interface>(const std::string &name,
2507
                                                                                 std::vector<std::shared_ptr<Features::FaultModels::Composition::Interface> > &vector);
2508
  /**
2509
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2510
  * Note that the variable with this name has to be loaded before this function is called.
2511
  */
2512
  template bool
2513
  Parameters::get_shared_pointers<Features::FaultModels::Grains::Interface>(const std::string &name,
2514
                                                                            std::vector<std::shared_ptr<Features::FaultModels::Grains::Interface> > &vector);
2515
  /**
2516
  * Todo: Returns a vector of pointers to the Point<3> Type based on the provided name.
2517
  * Note that the variable with this name has to be loaded before this function is called.
2518
  */
2519
  template bool
2520
  Parameters::get_shared_pointers<Features::FaultModels::Velocity::Interface>(const std::string &name,
2521
                                                                              std::vector<std::shared_ptr<Features::FaultModels::Velocity::Interface> > &vector);
2522

2523

2524

2525

2526

2527
} // namespace WorldBuilder
2528

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc