ARTS 2.5.9 (git: 825fa5f2)
agenda_class.cc
Go to the documentation of this file.
1/* Copyright (C) 2002-2012
2 Stefan Buehler <sbuehler@ltu.se>
3 Oliver Lemke <olemke@core-dump.info>
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 USA. */
19
28#include <algorithm>
29#include <iterator>
30#include <memory>
31#include <ostream>
32
33#include "agenda_class.h"
34#include "agenda_record.h" // only for test functions
35#include "arts.h"
36#include "arts_omp.h"
37#include "auto_md.h"
38#include "debug.h"
39#include "global_data.h"
40#include "messages.h"
41#include "methods.h"
42#include "tokval.h"
43#include "workspace_ng.h"
44
45MRecord::MRecord() : moutput(), minput(), msetvalue(), mtasks() {}
46
48 : moutput(), minput(), msetvalue(), mtasks(ws) {}
49
51 ArrayOfIndex output,
52 ArrayOfIndex input,
53 const TokVal& setvalue,
54 const Agenda& tasks,
55 bool internal)
56 : mid(id),
57 moutput(std::move(output)),
58 minput(std::move(input)),
59 msetvalue(setvalue),
60 mtasks(tasks),
61 minternal(internal) {
62}
63
64
66 : ws(workspace.weak_from_this()),
67 mname(),
68 mml(),
69 moutput_push(),
70 moutput_dup() {}
71
73
87void Agenda::append(const String& methodname, const TokVal& keywordvalue) {
89
90 const auto i2 = MdMap.find(methodname);
91 ARTS_ASSERT(i2 != MdMap.end());
92 Index id = i2->second;
93
95 ArrayOfIndex output = md_data[id].Out();
96
97 // Find explicit method id in MdMap.
98 ArrayOfIndex input = md_data[id].InOnly();
99
100 mml.push_back(MRecord(id, output, input, keywordvalue, Agenda(*workspace())));
101 mchecked = false;
102}
103
105
109void Agenda::check(Workspace& ws_in, const Verbosity& verbosity) {
110 // Check that this agenda has a default workspace
111 if (not workspace().get()) {
112 mchecked = false;
113 return;
114 }
115
116 // Check that this workspace lives on ws_in
118 "Agendas must share workspace"
119 )
120
121 // Make external data visible
124
125 // First we have to find the lookup information for this agenda. We
126 // use AgendaMap for this.
127
128 auto mi = AgendaMap.find(mname);
129
130 // Find return end() if the string is not found. This means we deal with
131 // agenda defined in the control file and therefore we don't check its
132 // consistency. Custom agendas can't be executed and we delay the check
133 // until it is copied to a predefined agenda.
134 if (mi == AgendaMap.end()) {
135 mchecked = false;
136 return;
137 }
138
139 const AgRecord& this_data = agenda_data[mi->second];
140
141 // Ok, we have the lookup data now.
142
143 // Check that the output produced by the actual methods in the
144 // agenda corresponds to what is desired in the lookup data:
145 for (Index i = 0; i < this_data.Out().nelem(); ++i) {
146 // The WSV for which to check:
147 Index this_wsv = this_data.Out()[i];
148
149 if (!is_output(this_wsv)) {
150 ostringstream os;
151 os << "The agenda " << mname << " must generate the output WSV "
152 << (*ws_in.wsv_data_ptr)[this_wsv].Name() << ",\n"
153 << "but it does not. It only generates:\n";
154 for (Index j = 0; j < (*ws_in.wsv_data_ptr).nelem(); ++j)
155 if (is_output(j)) os << (*ws_in.wsv_data_ptr)[j].Name() << "\n";
156 throw runtime_error(os.str());
157 }
158 }
159
160 // Check that the input used by the actual methods in the
161 // agenda corresponds to what is desired in the lookup data:
162 for (Index i = 0; i < this_data.In().nelem(); ++i) {
163 // The WSV for which to check:
164 Index this_wsv = this_data.In()[i];
165
166 if (!is_input(ws_in, this_wsv)) {
167 ostringstream os;
168 os << "The agenda " << mname << " must use the input WSV "
169 << (*ws_in.wsv_data_ptr)[this_wsv].Name() << ",\n"
170 << "but it does not. It only uses:\n";
171 for (Index j = 0; j < (*ws_in.wsv_data_ptr).nelem(); ++j)
172 if (is_input(ws_in, j)) os << (*ws_in.wsv_data_ptr)[j].Name() << "\n";
173 throw runtime_error(os.str());
174 }
175 }
176
178
179 mchecked = true;
180}
181
183
188void Agenda::execute(Workspace& ws_in) const {
189 ARTS_USER_ERROR_IF (not mchecked, "Agenda *", mname, R"--(* hasn't been checked for consistency yet.
190
191This check is usually done by AgendaSet or AgendaAppend.
192
193There are three possible causes for this:
194 1) Custom agenda: You're trying to execute an agenda that has been
195 created manually. This is not allowed. You have to use one of
196 the predefined agendas and execute that one.
197 2) Developer error: If you have written code that modifies an Agenda
198 directly (changing its name or altering its method list), it's up
199 to you to call Agenda::check in your code after your modifications.
200 3) Workspace mismatch: All Agendas live on the workspace and can only
201 be executed by the workspace, or a child of the workspace, that
202 was originally connected to the workspace.
203)--")
204
206 not has_same_origin(ws_in), mname, " is on another original workspace.")
207
208 // An empty Agenda name indicates that something going wrong here
209 ARTS_ASSERT(mname != "");
210
211 // The method description lookup table:
213
214 // The array holding the pointers to the getaway functions:
215 extern void (*getaways[])(Workspace&, const MRecord&);
216
217 const Index wsv_id_verbosity = ws_in.WsvMap_ptr->at("verbosity");
218 ws_in.duplicate(wsv_id_verbosity);
219
220 Verbosity& averbosity =
221 *(static_cast<Verbosity*>(ws_in[wsv_id_verbosity].get()));
222
223 averbosity.set_main_agenda(is_main_agenda());
224
225 ArtsOut1 aout1(averbosity);
226 {
227 // ostringstream os; // disabled for performance reasons
228 // os << "Executing " << name() << "\n"
229 // << "{\n";
230 // aout1 << os.str();
231 aout1 << "Executing " << name() << "\n"
232 << "{\n";
233 }
234
235 for (Index i = 0; i < mml.nelem(); ++i) {
236 const Verbosity& verbosity =
237 *static_cast<Verbosity*>(ws_in[wsv_id_verbosity].get());
240
241 // Runtime method data for this method:
242 const MRecord& mrr = mml[i];
243 // Method data for this method:
244 const MdRecord& mdd = md_data[mrr.Id()];
245
246 try {
247 {
248 if (mrr.isInternal()) {
249 out3 << "- " + mdd.Name() + "\n";
250 } else {
251 out1 << "- " + mdd.Name() + "\n";
252 }
253 }
254
255 { // Check if all input variables are initialized:
256 const ArrayOfIndex& v(mrr.In());
257 for (Index s = 0; s < v.nelem(); ++s) {
258 if ((s != v.nelem() - 1 || !mdd.SetMethod()) &&
259 !ws_in.is_initialized(v[s]))
260 throw runtime_error(
261 "Method " + mdd.Name() +
262 " needs input variable: " + (*ws_in.wsv_data_ptr)[v[s]].Name());
263 }
264 }
265
266 { // Check if all output variables which are also used as input
267 // are initialized
268 const ArrayOfIndex& v = mdd.InOut();
269 for (Index s = 0; s < v.nelem(); ++s)
270 if (!ws_in.is_initialized(mrr.Out()[v[s]]))
271 throw runtime_error("Method " + mdd.Name() +
272 " needs input variable: " +
273 (*ws_in.wsv_data_ptr)[mrr.Out()[v[s]]].Name());
274 }
275
276 // Call the getaway function:
277 getaways[mrr.Id()](ws_in, mrr);
278
279 } catch (const std::bad_alloc& x) {
280 aout1 << "}\n";
281
282 ostringstream os;
283 os << "Memory allocation error in method: " << mdd.Name() << '\n'
284 << "For memory intensive jobs it could help to limit the\n"
285 << "number of threads with the -n option.\n"
286 << x.what();
287
288 throw runtime_error(os.str());
289 } catch (const std::exception& x) {
290 aout1 << "}\n";
291
292 ostringstream os;
293 os << "Run-time error in method: " << mdd.Name() << '\n' << x.what();
294
295 throw runtime_error(os.str());
296 }
297 }
298
299 aout1 << "}\n";
300
301 ws_in.pop(wsv_id_verbosity);
302}
303
305
314 using global_data::MdMap;
316
317 set<Index> inputs;
318 set<Index> outputs;
319 set<Index> outs2push;
320 set<Index> outs2dup;
321
322 const Index WsmAgendaExecuteIndex = MdMap.find("AgendaExecute")->second;
323 const Index WsmAgendaExecuteExclIndex =
324 MdMap.find("AgendaExecuteExclusive")->second;
325 const Index WsmDeleteIndex = MdMap.find("Delete")->second;
326 const Index WsvAgendaGroupIndex = WsvGroupMap.find("Agenda")->second;
327
328 for (auto & method : mml) {
329 // Collect output WSVs
330 const ArrayOfIndex& gouts = method.Out();
331
332 // Put the outputs into a new set to sort them. Otherwise
333 // set_intersection and set_difference screw up.
334 set<Index> souts;
335 souts.insert(gouts.begin(), gouts.end());
336
337 // Collect generic input WSVs
338 const ArrayOfIndex& gins = method.In();
339 inputs.insert(gins.begin(), gins.end());
340
341 /* Special case: For the Delete WSM add its input to the list
342 * of output variables to force a duplication of those variables.
343 * It avoids deleting variables outside the agenda's scope.
344 */
345 if (method.Id() == WsmDeleteIndex) {
346 souts.insert(gins.begin(), gins.end());
347 }
348
349 /* Special case: For WSMs that execute generic input Agendas
350 it is necessary for proper scoping to also add the output and input variables of the
351 agenda to our output and input variable lists.
352 */
353 if (method.Id() == WsmAgendaExecuteIndex ||
354 method.Id() == WsmAgendaExecuteExclIndex) {
355 for (Index j = 0; j < md_data[method.Id()].GInType().nelem(); j++) {
356 if (md_data[method.Id()].GInType()[j] == WsvAgendaGroupIndex) {
357 const String& agenda_name = (*workspace()->wsv_data_ptr)[gins[j]].Name();
358 const auto agenda_it =
359 AgendaMap.find(agenda_name);
360 // The executed agenda must not be a user created agenda
361 if (agenda_it == AgendaMap.end()) {
362 ostringstream os;
363 os << "Manual execution of the agenda \"" << agenda_name
364 << "\" is not supported.";
365 throw std::runtime_error(os.str());
366 }
367 const ArrayOfIndex& agouts = agenda_data[agenda_it->second].Out();
368 souts.insert(agouts.begin(), agouts.end());
369 const ArrayOfIndex& agins = agenda_data[agenda_it->second].In();
370 inputs.insert(agins.begin(), agins.end());
371 }
372 }
373 }
374
375 // Add all outputs of this WSM to global list of outputs
376 outputs.insert(souts.begin(), souts.end());
377
378 // Find out all output WSVs of current WSM which were
379 // already used as input. We have to place a copy of them on
380 // the WSV stack.
381 set_intersection(souts.begin(),
382 souts.end(),
383 inputs.begin(),
384 inputs.end(),
385 insert_iterator<set<Index> >(outs2dup, outs2dup.begin()));
386
387 // Get a handle on the InOut list for the current method:
388 const ArrayOfIndex& mdinout = md_data[method.Id()].InOut();
389 const ArrayOfIndex& output = method.Out();
390
391 for (Index j = 0; j < mdinout.nelem(); j++) {
392 inputs.insert(output[mdinout[j]]);
393 }
394 }
395
396 // Find all outputs which are not in the list of WSVs to duplicate
397 set_difference(outputs.begin(),
398 outputs.end(),
399 outs2dup.begin(),
400 outs2dup.end(),
401 insert_iterator<set<Index> >(outs2push, outs2push.begin()));
402
403 const auto [ain, aout] = get_global_inout();
404
405 // We have to build a new set of agenda input and output because the
406 // set_difference function only works properly on sorted input.
407 set<Index> saout;
408 set<Index> sain;
409
410 saout.insert(aout.begin(), aout.end());
411 sain.insert(ain.begin(), ain.end());
412
413 moutput_push.clear();
414 moutput_dup.clear();
415
416 // Remove the WSVs which are agenda input from the list of
417 // output variables for which we have to create an new
418 // entry on the stack. This is already done for agenda inputs.
419 set<Index> outs2push_without_agenda_input;
420 set_difference(
421 outs2push.begin(),
422 outs2push.end(),
423 sain.begin(),
424 sain.end(),
425 insert_iterator<set<Index> >(outs2push_without_agenda_input,
426 outs2push_without_agenda_input.begin()));
427
428 // Same for agenda output variables.
429 set_difference(
430 outs2push_without_agenda_input.begin(),
431 outs2push_without_agenda_input.end(),
432 saout.begin(),
433 saout.end(),
434 insert_iterator<ArrayOfIndex>(moutput_push, moutput_push.begin()));
435
436 // Remove the WSVs which are agenda input from the list of
437 // output variables for which we have to create a duplicate
438 // on the stack. This is already done for agenda inputs.
439 set<Index> outs2dup_without_agenda_input;
440 set_difference(
441 outs2dup.begin(),
442 outs2dup.end(),
443 sain.begin(),
444 sain.end(),
445 insert_iterator<set<Index> >(outs2dup_without_agenda_input,
446 outs2dup_without_agenda_input.begin()));
447
448 // Same for agenda output variables.
449 set_difference(
450 outs2dup_without_agenda_input.begin(),
451 outs2dup_without_agenda_input.end(),
452 saout.begin(),
453 saout.end(),
454 insert_iterator<ArrayOfIndex>(moutput_dup, moutput_dup.begin()));
455
456 // Special case: Variables which are defined in the agenda only
457 // as output but are used first as input in one of the WSMs
458 // For those the current WSV value must be copied to the agenda
459 // input variable
460 set<Index> saout_only;
461
462 set_difference(saout.begin(),
463 saout.end(),
464 sain.begin(),
465 sain.end(),
466 insert_iterator<set<Index> >(saout_only, saout_only.begin()));
467
468 ArrayOfIndex agenda_only_out_wsm_in;
469 set_intersection(outs2dup.begin(),
470 outs2dup.end(),
471 saout_only.begin(),
472 saout_only.end(),
473 insert_iterator<ArrayOfIndex>(
474 agenda_only_out_wsm_in, agenda_only_out_wsm_in.begin()));
475
476 // Special case: Variables which are defined in the agenda only
477 // as input but are used as output in one of the WSMs
478 // For those the current WSV value must be copied to the agenda
479 // input variable
480 set<Index> sain_only;
481
482 set_difference(sain.begin(),
483 sain.end(),
484 saout.begin(),
485 saout.end(),
486 insert_iterator<set<Index> >(sain_only, sain_only.begin()));
487
488 ArrayOfIndex agenda_only_in_wsm_out;
489 set_intersection(outs2push.begin(),
490 outs2push.end(),
491 sain_only.begin(),
492 sain_only.end(),
493 insert_iterator<ArrayOfIndex>(
494 agenda_only_in_wsm_out, agenda_only_in_wsm_out.begin()));
495
497
498 out3 << " [Agenda::pushpop] : " << name() << "\n";
499 out3 << " [Agenda::pushpop] - # Funcs in Ag : " << mml.nelem() << "\n";
500 out3 << " [Agenda::pushpop] - AgOut : ";
501 PrintWsvNames(out3, *workspace(), aout);
502 out3 << "\n";
503 out3 << " [Agenda::pushpop] - AgIn : ";
504 PrintWsvNames(out3, *workspace(), ain);
505 out3 << "\n";
506 out3 << " [Agenda::pushpop] - All WSM output: ";
507 PrintWsvNames(out3, *workspace(), outputs);
508 out3 << "\n";
509 out3 << " [Agenda::pushpop] - All WSM input : ";
510 PrintWsvNames(out3, *workspace(), inputs);
511 out3 << "\n";
512 out3 << " [Agenda::pushpop] - Output WSVs push : ";
514 out3 << "\n";
515 out3 << " [Agenda::pushpop] - Output WSVs dup : ";
517 out3 << "\n";
518 out3 << " [Agenda::pushpop] - Ag inp dup : ";
519 PrintWsvNames(out3, *workspace(), agenda_only_in_wsm_out);
520 out3 << "\n";
521 out3 << " [Agenda::pushpop] - Ag out dup : ";
522 PrintWsvNames(out3, *workspace(), agenda_only_out_wsm_in);
523 out3 << "\n";
524}
525
527
535bool Agenda::is_input(Workspace& ws_in, Index var) const {
536 // Make global method data visible:
540 using global_data::MdMap;
542
543 const Index WsmAgendaExecuteIndex = MdMap.find("AgendaExecute")->second;
544 const Index WsmAgendaExecuteExclIndex =
545 MdMap.find("AgendaExecuteExclusive")->second;
546
547 // Make sure that var is the index of a valid WSV:
548 ARTS_ASSERT(0 <= var);
549 ARTS_ASSERT(var < (*ws_in.wsv_data_ptr).nelem());
550
551 // Determine the index of WsvGroup Agenda
552 const Index WsvAgendaGroupIndex = WsvGroupMap.find("Agenda")->second;
553
554 // Loop all methods in this agenda:
555 for (Index i = 0; i < nelem(); ++i) {
556 // Get a handle on this methods runtime data record:
557 const MRecord& this_method = mml[i];
558
559 // Is var a generic input?
560 {
561 // Get a handle on the Input list:
562 const ArrayOfIndex& input = this_method.In();
563
564 for (Index j = 0; j < input.nelem(); ++j) {
565 if (var == input[j]) return true;
566 }
567
568 // Get a handle on the InOut list for the current method:
569 const ArrayOfIndex& mdinout = md_data[this_method.Id()].InOut();
570 const ArrayOfIndex& output = this_method.Out();
571
572 for (Index j = 0; j < mdinout.nelem(); j++) {
573 if (var == output[mdinout[j]]) return true;
574 }
575
576 /* Special case: For WSMs that execute generic input Agendas
577 it is necessary to check their inputs.
578 */
579 if (this_method.Id() == WsmAgendaExecuteIndex ||
580 this_method.Id() == WsmAgendaExecuteExclIndex) {
581 for (Index j = 0; j < md_data[this_method.Id()].GInType().nelem();
582 j++) {
583 if (md_data[this_method.Id()].GInType()[j] == WsvAgendaGroupIndex) {
584 const String& agenda_name = (*ws_in.wsv_data_ptr)[input[j]].Name();
585 const auto agenda_it =
586 AgendaMap.find(agenda_name);
587 // The executed agenda must not be a user created agenda
588 if (agenda_it == AgendaMap.end()) {
589 ostringstream os;
590 os << "Manual execution of the agenda \"" << agenda_name
591 << "\" is not supported.";
592 throw std::runtime_error(os.str());
593 }
594 const ArrayOfIndex& agins = agenda_data[agenda_it->second].In();
595 for (Index k = 0; k < agins.nelem(); ++k) {
596 if (var == agins[k]) return true;
597 }
598 }
599 }
600 }
601 }
602 }
603
604 // Ok, that means var is no input at all.
605 return false;
606}
607
609
617bool Agenda::is_output(Index var) const {
618 // Make global method data visible:
622 using global_data::MdMap;
624
625 const Index WsmAgendaExecuteIndex = MdMap.find("AgendaExecute")->second;
626 const Index WsmAgendaExecuteExclIndex =
627 MdMap.find("AgendaExecuteExclusive")->second;
628
629 // Determine the index of WsvGroup Agenda
630 const Index WsvAgendaGroupIndex = WsvGroupMap.find("Agenda")->second;
631
632 // Loop all methods in this agenda:
633 for (Index i = 0; i < nelem(); ++i) {
634 // Get a handle on this methods runtime data record:
635 const MRecord& this_method = mml[i];
636
637 // Is var a generic output?
638 {
639 // Get a handle on the Output list:
640 const ArrayOfIndex& output = this_method.Out();
641
642 for (Index j = 0; j < output.nelem(); ++j) {
643 if (var == output[j]) return true;
644 }
645
646 /* Special case: For WSMs that execute generic input Agendas
647 it is necessary to check their outputs.
648 */
649 if (this_method.Id() == WsmAgendaExecuteIndex ||
650 this_method.Id() == WsmAgendaExecuteExclIndex) {
651 for (Index j = 0; j < md_data[this_method.Id()].GInType().nelem();
652 j++) {
653 if (md_data[this_method.Id()].GInType()[j] == WsvAgendaGroupIndex) {
654 const String& agenda_name =
655 (*workspace()->wsv_data_ptr)[this_method.In()[j]].Name();
656 const auto agenda_it =
657 AgendaMap.find(agenda_name);
658 // The executed agenda must not be a user created agenda
659 if (agenda_it == AgendaMap.end()) {
660 ostringstream os;
661 os << "Manual execution of the agenda \"" << agenda_name
662 << "\" is not supported.";
663 throw std::runtime_error(os.str());
664 }
665 const ArrayOfIndex& agouts = agenda_data[agenda_it->second].Out();
666 for (Index k = 0; k < agouts.nelem(); k++)
667 if (agouts[k] == var) return true;
668 }
669 }
670 }
671 }
672 }
673
674 // Ok, that means var is no output at all.
675 return false;
676}
677
679
684void Agenda::set_name(const String& nname) {
685 mname = nname;
686 mchecked = false;
687}
688
690
695String Agenda::name() const { return mname; }
696
698
709bool Agenda::has_method(const String& methodname) const {
711
712 bool found = false;
713 for (auto it = mml.begin();
714 !found && it != mml.end();
715 it++) {
716 if (md_data[it->Id()].Name() == methodname) found = true;
717 }
718
719 return found;
720}
721
723 mml = ml;
724 mchecked = false;
725}
726
728
738void Agenda::print(ostream& os, const String& indent) const {
739 for (Index i = 0; i < mml.nelem(); ++i) {
740 // Print member methods with 3 characters more indentation:
741 mml[i].print(os, indent);
742 }
743}
744
746
749void Agenda::resize(Index n) { mml.resize(n); }
750
752
758Index Agenda::nelem() const { return mml.nelem(); }
759
761
767 mml.push_back(n);
768 mchecked = false;
769}
770
772 ws = x.ws;
773 mml = x.mml;
774 mname = x.mname;
777 mchecked = x.mchecked;
778 return *this;
779}
780
781bool Agenda::has_same_origin(const Workspace& ws2) const {return workspace()->original_workspace == ws2.original_workspace;}
782
783std::shared_ptr<Workspace> Agenda::workspace() const {
784 auto workspace = ws.lock();
785 ARTS_USER_ERROR_IF(workspace == nullptr,
786 "This agenda does not contain a valid Workspace.\n"
787 "The workspace might have gotten deleted, or\n"
788 "you're accessing a default-constructed agenda.");
789 return workspace;
790}
791
793
804ostream& operator<<(ostream& os, const Agenda& a) {
805 // Print agenda as it would apear in a controlfile.
806 a.print(os, " ");
807 return os;
808}
809
810//--------------------------------
811// Functions for MRecord:
812//--------------------------------
813
815
835void MRecord::print(ostream& os, const String& indent) const {
837
838 // Get a handle on the right record:
839 const MdRecord& tmd = md_data[Id()];
840
841 os << indent << tmd.Name();
842
843 // Is this a generic method? -- Then we need round braces.
844 if (0 != tmd.GOutType().nelem() + tmd.GInType().nelem()) {
845 // First entry needs no leading comma:
846 bool first = true;
847
848 os << "(";
849
850 for (Index i = 0; i < Out().nelem(); ++i) {
851 if (first)
852 first = false;
853 else
854 os << ",";
855
856 os << mtasks.workspace()->wsv_data_ptr->operator[](Out()[i]).Name();
857 }
858
859 for (Index i = 0; i < In().nelem(); ++i) {
860 if (first)
861 first = false;
862 else
863 os << ",";
864
865 os << mtasks.workspace()->wsv_data_ptr->operator[](In()[i]).Name();
866 }
867
868 os << ")";
869 }
870
871 if (0 != Tasks().nelem()) {
872 os << " {\n";
873 Tasks().print(os, indent + " ");
874 os << indent << "}\n";
875 } else
876 os << "\n";
877}
878
880 mid = x.mid;
881
883
884 moutput = x.moutput;
885
886 minput = x.minput;
887
888 mtasks = x.mtasks;
889
890 return *this;
891}
892
893void MRecord::ginput_only(ArrayOfIndex& ginonly) const {
894 ginonly = minput; // Input
895 for (auto j = moutput.begin(); j < moutput.end(); ++j)
896 for (auto k = ginonly.begin(); k < ginonly.end(); ++k)
897 if (*j == *k) {
898 // erase_vector_element(vi,k);
899 k = ginonly.erase(k) - 1;
900 // We need the -1 here, otherwise due to the
901 // following increment we would miss the element
902 // behind the erased one, which is now at the
903 // position of the erased one.
904 }
905}
906
908
919ostream& operator<<(ostream& os, const MRecord& a) {
920 a.print(os, "");
921 return os;
922}
923
925 ArrayOfAgenda out;
926 for (auto& ag : agendas) out.push_back(ag.deepcopy_if(ws));
927 return out;
928}
929
930// Method to share indices of variables from one workspace to another
932 const Workspace& ws_in,
933 const ArrayOfIndex& vars) {
934 return ws_out.wsvs(ws_in.wsvs(vars));
935}
936
938 if (mtasks.has_same_origin(workspace)) return *this;
939
940 MRecord out(workspace);
941
942 out.mid = mid;
943 out.moutput = make_same_wsvs(workspace, *mtasks.workspace(), moutput);
944 out.minput = make_same_wsvs(workspace, *mtasks.workspace(), minput);
945 out.msetvalue = msetvalue;
946 out.mtasks = mtasks.deepcopy_if(workspace);
947 out.minternal = minternal;
948
949 return out;
950}
951
953 if (has_same_origin(workspace)) return *this;
954
955 Agenda out(workspace);
956 out.mname = mname;
957 for (auto& method : mml) out.mml.push_back(method.deepcopy_if(workspace));
961 out.mchecked = mchecked;
962
963 return out;
964}
965
966std::pair<ArrayOfIndex, ArrayOfIndex> Agenda::get_global_inout() const {
969 ArrayOfIndex aout;
970 ArrayOfIndex ain;
971 if (auto agenda_it = AgendaMap.find(name());
972 agenda_it != AgendaMap.end()) {
973 const AgRecord& agr = agenda_data[agenda_it->second];
974 aout = agr.Out();
975 ain = agr.In();
976 }
977 return {ain, aout};
978}
979
981 ws = x.shared_from_this();
982 for (auto& mr: mml) {
983 mr.set_workspace(x);
984 }
985}
986
989 if (msetvalue.holdsAgenda()) {
991 a.set_workspace(x);
992 msetvalue = a;
993 } else if (msetvalue.holdsArrayOfAgenda()) {
995 for (auto& b: a) b.set_workspace(x);
996 msetvalue = a;
997 }
998}
ArrayOfIndex make_same_wsvs(Workspace &ws_out, const Workspace &ws_in, const ArrayOfIndex &vars)
ArrayOfAgenda deepcopy_if(Workspace &ws, const ArrayOfAgenda &agendas)
Same as Agenda member method but for an entire array.
ostream & operator<<(ostream &os, const Agenda &a)
Output operator for Agenda.
Declarations for agendas.
void PrintWsvNames(OutputStream &outstream, const Workspace &ws, const Container &container)
Print list of WSV names to output stream.
Definition: agenda_class.h:52
Declarations for AgRecord, storing lookup information for one agenda.
The global header file for ARTS.
Header file for helper functions for OpenMP.
void(* getaways[])(Workspace &, const MRecord &)
Definition: auto_md.cc:22343
Lookup information for one agenda.
Definition: agenda_record.h:43
const ArrayOfIndex & Out() const
Definition: agenda_record.h:61
const ArrayOfIndex & In() const
Definition: agenda_record.h:62
The Agenda class.
Definition: agenda_class.h:69
bool mchecked
Flag indicating that the agenda was checked for consistency.
Definition: agenda_class.h:131
bool has_same_origin(const Workspace &ws2) const
void print(ostream &os, const String &indent) const
Print an agenda.
std::weak_ptr< Workspace > ws
Definition: agenda_class.h:119
void append(const String &methodname, const TokVal &keywordvalue)
Appends methods to an agenda.
Definition: agenda_class.cc:87
String name() const
Agenda name.
Array< MRecord > mml
Definition: agenda_class.h:121
void execute(Workspace &ws_in) const
Execute an agenda.
bool has_method(const String &methodname) const
Check if method is in Agenda.
void set_workspace(Workspace &x)
bool is_output(Index var) const
Check if given variable is agenda output.
bool main_agenda
Is set to true if this is the main agenda.
Definition: agenda_class.h:128
void set_methods(const Array< MRecord > &ml)
void check(Workspace &ws_in, const Verbosity &verbosity)
Checks consistency of an agenda.
bool is_input(Workspace &ws_in, Index var) const
Check if given variable is agenda input.
Agenda & operator=(const Agenda &x)
std::pair< ArrayOfIndex, ArrayOfIndex > get_global_inout() const
Get index lists of global input and output variables from agenda_data of this agenda.
void set_outputs_to_push_and_dup(const Verbosity &verbosity)
Retrieve indexes of all input and output WSVs.
void push_back(const MRecord &n)
Append a new method to end of list.
Agenda deepcopy_if(Workspace &) const
Creates a deep copy of the agenda if necessary (i.e., different workspace)!
Agenda()=default
String mname
Definition: agenda_class.h:120
void resize(Index n)
Resize the method list.
ArrayOfIndex moutput_push
Definition: agenda_class.h:123
std::shared_ptr< Workspace > workspace() const
void set_name(const String &nname)
Set agenda name.
ArrayOfIndex moutput_dup
Definition: agenda_class.h:125
bool is_main_agenda() const
Definition: agenda_class.h:101
Index nelem() const
Return the number of agenda elements.
Index nelem() const ARTS_NOEXCEPT
Definition: array.h:92
Index nelem() const noexcept
Returns the number of elements.
Definition: matpackI.h:547
Method runtime data.
Definition: agenda_class.h:142
Agenda mtasks
An agenda, which can be given in the controlfile instead of keywords.
Definition: agenda_class.h:228
const ArrayOfIndex & In() const
Definition: agenda_class.h:159
ArrayOfIndex minput
Input workspace variables.
Definition: agenda_class.h:223
void set_workspace(Workspace &x)
MRecord & operator=(const MRecord &x)
Assignment operator for MRecord.
const Agenda & Tasks() const
Definition: agenda_class.h:161
void print(ostream &os, const String &indent) const
Print an MRecord.
bool minternal
Flag if this method is called internally by the engine.
Definition: agenda_class.h:230
MRecord deepcopy_if(Workspace &) const
Creates a deep copy of the method if necessary (i.e., different workspace)!
ArrayOfIndex moutput
Output workspace variables.
Definition: agenda_class.h:221
Index Id() const
Definition: agenda_class.h:157
Index mid
Method id.
Definition: agenda_class.h:219
void ginput_only(ArrayOfIndex &ginonly) const
Get list of generic input only WSVs.
bool isInternal() const
Indicates the origin of this method.
Definition: agenda_class.h:174
const ArrayOfIndex & Out() const
Definition: agenda_class.h:158
TokVal msetvalue
Keyword value for Set methods.
Definition: agenda_class.h:225
All information for one workspace method.
Definition: methods.h:38
const String & Name() const
Definition: methods.h:85
const ArrayOfIndex & GOutType() const
Definition: methods.h:90
const ArrayOfIndex & InOut() const
Definition: methods.h:100
bool SetMethod() const
Definition: methods.h:102
const ArrayOfIndex & GInType() const
Definition: methods.h:95
Definition: tokval.h:245
bool holdsAgenda() const
Definition: tokval.cc:202
bool holdsArrayOfAgenda() const
Definition: tokval.cc:205
void set_main_agenda(bool main_agenda)
Definition: messages.h:72
Workspace class.
Definition: workspace_ng.h:53
std::shared_ptr< wsv_data_type > wsv_data_ptr
Definition: workspace_ng.h:76
void pop(Index i)
Remove the topmost WSV from its stack.
T * get(const char *name)
Retrieve a value ptr if it exist (FIXME: C++20 allows const char* as template argument)
Definition: workspace_ng.h:188
bool is_initialized(Index i) const
Checks existence of the given WSV.
wsv_data_type wsvs(const ArrayOfIndex &) const
Workspace * original_workspace
Definition: workspace_ng.h:81
void duplicate(Index i)
Duplicate WSV.
Definition: workspace_ng.cc:56
std::shared_ptr< WsvMap_type > WsvMap_ptr
Definition: workspace_ng.h:79
Helper macros for debugging.
#define ARTS_ASSERT(condition,...)
Definition: debug.h:82
#define ARTS_USER_ERROR_IF(condition,...)
Definition: debug.h:134
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
Declarations having to do with the four output streams.
#define CREATE_OUT1
Definition: messages.h:204
#define CREATE_OUT3
Definition: messages.h:206
Declaration of the class MdRecord.
const Array< MdRecord > md_data
Lookup information for workspace methods.
Definition: methods_aux.cc:50
const map< String, Index > MdMap
The map associated with md_data.
Definition: methods_aux.cc:41
const Array< AgRecord > agenda_data
The lookup information for the agendas.
Definition: agendas.cc:41
const map< String, Index > WsvGroupMap
The map associated with wsv_groups.
Definition: groups.cc:43
map< String, Index > AgendaMap
The map associated with agenda_data.
#define v
#define a
#define b
This file contains the Workspace class.