00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00028 #include <ostream>
00029 #include <algorithm>
00030 #include <iterator>
00031
00032 #include "arts.h"
00033 #include "agenda_class.h"
00034 #include "agenda_record.h"
00035 #include "methods.h"
00036 #include "wsv_aux.h"
00037 #include "messages.h"
00038 #include "workspace_ng.h"
00039 #include "arts_omp.h"
00040 #include "auto_md.h"
00041
00042
00044 void give_up(const String& message)
00045 {
00046 out0 << message << '\n';
00047 arts_exit();
00048 }
00049
00050
00052
00067 void Agenda::append(Workspace& ws _U_,
00068 const String& methodname,
00069 const TokVal& keywordvalue)
00070 {
00071 extern const map<String, Index> MdMap;
00072
00073 const map<String, Index>::const_iterator i2 = MdMap.find(methodname);
00074 assert ( i2 != MdMap.end() );
00075 Index id = i2->second;
00076
00077 extern const Array<MdRecord> md_data;
00078 ArrayOfIndex output = md_data[id].Out();
00079
00080
00081 ArrayOfIndex input = md_data[id].In();
00082 Agenda dummy;
00083 dummy.resize(0);
00084
00085
00086 dummy.push_back (MRecord(id,output,input,keywordvalue,dummy));
00087 AgendaAppend(ws, *this, mname, *this, mname, dummy);
00088 }
00089
00090
00092
00096 void Agenda::check(Workspace& ws)
00097 {
00098
00099 extern const Array<AgRecord> agenda_data;
00100 extern const map<String, Index> AgendaMap;
00101
00102
00103
00104
00105 map<String, Index>::const_iterator mi =
00106 AgendaMap.find( mname );
00107
00108
00109
00110 assert( mi != AgendaMap.end() );
00111
00112 const AgRecord& this_data = agenda_data[mi->second];
00113
00114
00115
00116
00117
00118 for ( Index i=0; i<this_data.Out().nelem(); ++i )
00119 {
00120
00121 Index this_wsv = this_data.Out()[i];
00122
00123 if ( !is_output(this_wsv) )
00124 {
00125 ostringstream os;
00126 os << "The agenda " << mname
00127 << " must generate the output WSV "
00128 << Workspace::wsv_data[this_wsv].Name() << ",\n"
00129 << "but it does not. It only generates:\n";
00130 for ( Index j=0; j<Workspace::wsv_data.nelem(); ++j )
00131 if ( is_output(j) )
00132 os << Workspace::wsv_data[j].Name() << "\n";
00133 throw runtime_error (os.str());
00134 }
00135 }
00136
00137
00138
00139 for ( Index i=0; i<this_data.In().nelem(); ++i )
00140 {
00141
00142 Index this_wsv = this_data.In()[i];
00143
00144 if ( !is_input(ws, this_wsv) )
00145 {
00146 ostringstream os;
00147 os << "The agenda " << mname
00148 << " must use the input WSV "
00149 << Workspace::wsv_data[this_wsv].Name() << ",\n"
00150 << "but it does not. It only uses:\n";
00151 for ( Index j=0; j<Workspace::wsv_data.nelem(); ++j )
00152 if ( is_input(ws, j) )
00153 os << Workspace::wsv_data[j].Name() << "\n";
00154 throw runtime_error (os.str());
00155 }
00156 }
00157
00158 set_outputs_to_push_and_dup ();
00159
00160 mchecked = true;
00161 }
00162
00163
00165
00170 void Agenda::execute(Workspace& ws) const
00171 {
00172
00173 if (!mchecked)
00174 {
00175 ostringstream os;
00176 os << "Agenda *" << mname << "* hasn't been checked for consistency yet."
00177 << endl
00178 << "This check is usually done by AgendaSet or AgendaAppend."
00179 << endl
00180 << "However, if you have written code that modifies an Agenda directly"
00181 << endl
00182 << "(changing its name or altering its method list), it's up to you to"
00183 << endl
00184 << "call Agenda::check after your modifications.";
00185 throw runtime_error(os.str());
00186 }
00187
00188
00189
00190
00191
00192 bool original_in_main_agenda = in_main_agenda;
00193 in_main_agenda = is_main_agenda();
00194
00195
00196 assert (mname != "");
00197
00198
00199 extern const Array<MdRecord> md_data;
00200
00201
00202 extern void (*getaways[])(Workspace&, const MRecord&);
00203
00204 out1 << "Executing " << name() << "\n"
00205 << "{\n";
00206
00207 for (Index i=0; i<mml.nelem(); ++i)
00208 {
00209
00210 const MRecord& mrr = mml[i];
00211
00212 const MdRecord& mdd = md_data[mrr.Id()];
00213
00214 try
00215 {
00216 {
00217 ostringstream os;
00218 if ((mdd.SetMethod() && mrr.Out().nelem()
00219 && Workspace::wsv_data[mrr.Out()[0]].Name().substr(0, 5)
00220 == "auto_")
00221 || (mdd.Name() == "Delete" && mrr.In().nelem()
00222 && Workspace::wsv_data[mrr.In()[0]].Name().substr(0, 5)
00223 == "auto_"))
00224 {
00225 out3 << "- " << mdd.Name() << "\n";
00226 }
00227 else
00228 {
00229 out1 << "- " << mdd.Name() << "\n";
00230 }
00231 }
00232
00233 {
00234 const ArrayOfIndex& v(mrr.In());
00235 for (Index s=0; s<v.nelem(); ++s)
00236 if ((s != v.nelem()-1 || !mdd.SetMethod())
00237 && !ws.is_initialized(v[s]) )
00238 give_up("Method "+mdd.Name()+" needs input variable: "+
00239 Workspace::wsv_data[v[s]].Name());
00240 }
00241
00242 {
00243
00244 const ArrayOfIndex& v = mdd.InOut();
00245 for (Index s=0; s<v.nelem(); ++s)
00246 if (!ws.is_initialized(mrr.Out()[v[s]]) )
00247 give_up("Method "+mdd.Name()+" needs input variable: "+
00248 Workspace::wsv_data[mrr.Out()[v[s]]].Name());
00249 }
00250
00251
00252 getaways[mrr.Id()]( ws, mrr );
00253
00254 }
00255 catch (runtime_error x)
00256 {
00257 ostringstream os;
00258 os << "Run-time error in method: " << mdd.Name() << '\n'
00259 << x.what();
00260
00261
00262
00263
00264
00265 in_main_agenda = original_in_main_agenda;
00266
00267 out1 << "}\n";
00268
00269 throw runtime_error(os.str());
00270 }
00271 }
00272
00273 out1 << "}\n";
00274
00275
00276 in_main_agenda = original_in_main_agenda;
00277 }
00278
00279
00281
00286 void Agenda::set_outputs_to_push_and_dup ()
00287 {
00288 extern const Array<MdRecord> md_data;
00289
00290 set<Index> inputs;
00291 set<Index> outputs;
00292 set<Index> outs2push;
00293 set<Index> outs2dup;
00294
00295 for (Array<MRecord>::const_iterator method = mml.begin ();
00296 method != mml.end (); method++)
00297 {
00298
00299 const ArrayOfIndex& outs = md_data[method->Id()].Out();
00300 const ArrayOfIndex& gouts = method->Out();
00301
00302
00303
00304 set<Index> souts;
00305 souts.insert ( outs.begin (), outs.end ());
00306 souts.insert ( gouts.begin (), gouts.end ());
00307
00308
00309 const ArrayOfIndex& gins = method->In();
00310 inputs.insert (gins.begin (), gins.end ());
00311
00312
00313
00314
00315
00316 if (md_data[method->Id()].Name() == "Delete")
00317 {
00318 souts.insert ( gins.begin (), gins.end ());
00319 }
00320
00321
00322 const ArrayOfIndex& ins = md_data[method->Id()].In();
00323 inputs.insert (ins.begin (), ins.end ());
00324
00325
00326 outputs.insert (souts.begin (), souts.end ());
00327
00328
00329
00330
00331 set_intersection (souts.begin (), souts.end (),
00332 inputs.begin (), inputs.end (),
00333 insert_iterator< set<Index> >(outs2dup,
00334 outs2dup.begin ()));
00335
00336 }
00337
00338
00339 set_difference (outputs.begin (), outputs.end (),
00340 outs2dup.begin (), outs2dup.end (),
00341 insert_iterator< set<Index> >(outs2push,
00342 outs2push.begin ()));
00343
00344 extern const map<String, Index> AgendaMap;
00345 extern const Array<AgRecord> agenda_data;
00346
00347 const AgRecord& agr = agenda_data[AgendaMap.find (name ())->second];
00348 const ArrayOfIndex& aout = agr.Out();
00349 const ArrayOfIndex& ain = agr.In();
00350
00351
00352
00353 set<Index> saout;
00354 set<Index> sain;
00355
00356 saout.insert ( aout.begin (), aout.end ());
00357 sain.insert ( ain.begin (), ain.end ());
00358
00359 moutput_push.clear ();
00360 moutput_dup.clear ();
00361
00362
00363
00364
00365 set<Index> outs2push_without_agenda_input;
00366 set_difference (outs2push.begin (), outs2push.end (),
00367 sain.begin (), sain.end (),
00368 insert_iterator< set<Index> >(outs2push_without_agenda_input,
00369 outs2push_without_agenda_input.begin ()));
00370
00371
00372 set_difference (outs2push_without_agenda_input.begin (),
00373 outs2push_without_agenda_input.end (),
00374 saout.begin (), saout.end (),
00375 insert_iterator<ArrayOfIndex>(moutput_push,
00376 moutput_push.begin ()));
00377
00378
00379
00380
00381 set<Index> outs2dup_without_agenda_input;
00382 set_difference (outs2dup.begin (), outs2dup.end (),
00383 sain.begin (), sain.end (),
00384 insert_iterator< set<Index> >(outs2dup_without_agenda_input,
00385 outs2dup_without_agenda_input.begin ()));
00386
00387
00388 set_difference (outs2dup_without_agenda_input.begin (),
00389 outs2dup_without_agenda_input.end (),
00390 saout.begin (), saout.end (),
00391 insert_iterator<ArrayOfIndex>(moutput_dup,
00392 moutput_dup.begin ()));
00393
00394
00395
00396
00397
00398 set<Index> saout_only;
00399
00400 set_difference (saout.begin (), saout.end (),
00401 sain.begin (), sain.end (),
00402 insert_iterator< set<Index> >(saout_only,
00403 saout_only.begin ()));
00404
00405 ArrayOfIndex agenda_only_out_wsm_in;
00406 set_intersection (outs2dup.begin (), outs2dup.end (),
00407 saout_only.begin (), saout_only.end (),
00408 insert_iterator<ArrayOfIndex>(agenda_only_out_wsm_in,
00409 agenda_only_out_wsm_in.begin ()));
00410
00411
00412
00413
00414
00415 set<Index> sain_only;
00416
00417 set_difference (sain.begin (), sain.end (),
00418 saout.begin (), saout.end (),
00419 insert_iterator< set<Index> >(sain_only,
00420 sain_only.begin ()));
00421
00422 ArrayOfIndex agenda_only_in_wsm_out;
00423 set_intersection (outs2push.begin (), outs2push.end (),
00424 sain_only.begin (), sain_only.end (),
00425 insert_iterator<ArrayOfIndex>(agenda_only_in_wsm_out,
00426 agenda_only_in_wsm_out.begin ()));
00427
00428 out3 << " [Agenda::pushpop] : " << name() << "\n";
00429 out3 << " [Agenda::pushpop] - # Funcs in Ag : " << mml.nelem () << "\n";
00430 out3 << " [Agenda::pushpop] - AgOut : ";
00431 PrintWsvNames (out3, aout);
00432 out3 << "\n";
00433 out3 << " [Agenda::pushpop] - AgIn : ";
00434 PrintWsvNames (out3, ain);
00435 out3 << "\n";
00436 out3 << " [Agenda::pushpop] - All WSM output: ";
00437 PrintWsvNames (out3, outputs);
00438 out3 << "\n";
00439 out3 << " [Agenda::pushpop] - WSVs push : ";
00440 PrintWsvNames (out3, moutput_push);
00441 out3 << "\n";
00442 out3 << " [Agenda::pushpop] - WSVs dup : ";
00443 PrintWsvNames (out3, moutput_dup);
00444 out3 << "\n";
00445 out3 << " [Agenda::pushpop] - Ag inp dup : ";
00446 PrintWsvNames (out3, agenda_only_in_wsm_out);
00447 out3 << "\n";
00448 out3 << " [Agenda::pushpop] - Ag out dup : ";
00449 PrintWsvNames (out3, agenda_only_out_wsm_in);
00450 out3 << "\n";
00451
00452 if (agenda_only_in_wsm_out.nelem ())
00453 {
00454 ostringstream err;
00455 err << "At least one variable is only defined as input\n"
00456 << "in agenda " << name () << ", but\n"
00457 << "used as output in a WSM called by the agenda!!!\n"
00458 << "This is not allowed.\n"
00459 << "Variable(s): ";
00460 PrintWsvNames (err, agenda_only_in_wsm_out);
00461 throw runtime_error (err.str ());
00462 }
00463 }
00464
00466
00475 bool Agenda::is_input(Workspace& ws, Index var) const
00476 {
00477
00478 extern const Array<MdRecord> md_data;
00479 extern const ArrayOfString wsv_group_names;
00480
00481
00482 assert( 0<=var );
00483 assert( var<md_data.nelem() );
00484
00485
00486 Index WsvAgendaGroupIndex = 0;
00487 for (Index i = 0; !WsvAgendaGroupIndex && i < wsv_group_names.nelem (); i++)
00488 {
00489 if (wsv_group_names[i] == "Agenda")
00490 WsvAgendaGroupIndex = i;
00491 }
00492
00493
00494 for ( Index i=0; i<nelem(); ++i )
00495 {
00496
00497 const MRecord& this_method = mml[i];
00498
00499
00500 {
00501
00502 const ArrayOfIndex& input = md_data[this_method.Id()].In();
00503
00504 for ( Index j=0; j<input.nelem(); ++j )
00505 {
00506 if ( var == input[j] ) return true;
00507 }
00508 }
00509
00510
00511 {
00512
00513 const ArrayOfIndex& input = this_method.In();
00514
00515 for ( Index j=0; j<input.nelem(); ++j )
00516 {
00517 if ( var == input[j] ) return true;
00518 }
00519 }
00520
00521
00522
00523 for ( Index j = 0; j < md_data[this_method.Id ()].GInType().nelem(); j++)
00524 {
00525 if (md_data[this_method.Id ()].GInType()[j] == WsvAgendaGroupIndex)
00526 {
00527 Agenda *AgendaFromGeneralInput =
00528 (Agenda *)ws[this_method.In()[j]];
00529
00530 if ((*AgendaFromGeneralInput).is_input(ws, var))
00531 {
00532 return true;
00533 }
00534 }
00535 }
00536 }
00537
00538
00539 return false;
00540 }
00541
00543
00551 bool Agenda::is_output(Index var) const
00552 {
00553
00554 for ( Index i=0; i<nelem(); ++i )
00555 {
00556
00557 const MRecord& this_method = mml[i];
00558
00559
00560 {
00561
00562 extern const Array<MdRecord> md_data;
00563
00564
00565 const ArrayOfIndex& output = md_data[this_method.Id()].Out();
00566
00567 for ( Index j=0; j<output.nelem(); ++j )
00568 {
00569 if ( var == output[j] ) return true;
00570 }
00571 }
00572
00573
00574 {
00575
00576 const ArrayOfIndex& output = this_method.Out();
00577
00578 for ( Index j=0; j<output.nelem(); ++j )
00579 {
00580 if ( var == output[j] ) return true;
00581 }
00582 }
00583 }
00584
00585
00586 return false;
00587 }
00588
00590
00595 void Agenda::set_name(const String& nname)
00596 {
00597 mname = nname;
00598 mchecked = false;
00599 }
00600
00602
00607 String Agenda::name() const
00608 {
00609 return mname;
00610 }
00611
00613
00623 void Agenda::print( ostream& os,
00624 const String& indent ) const
00625 {
00626 for ( Index i=0; i<mml.nelem(); ++i )
00627 {
00628
00629 mml[i].print(os,indent);
00630 }
00631 }
00632
00634
00645 ostream& operator<<(ostream& os, const Agenda& a)
00646 {
00647
00648 a.print(os, "");
00649 return os;
00650 }
00651
00652
00653
00654
00655
00657
00677 void MRecord::print( ostream& os,
00678 const String& indent ) const
00679 {
00680 extern const Array<MdRecord> md_data;
00681
00682
00683 const MdRecord tmd = md_data[Id()];
00684
00685 os << indent << tmd.Name();
00686
00687
00688 if ( 0 != tmd.GOutType().nelem()+tmd.GInType().nelem() )
00689 {
00690
00691 bool first=true;
00692
00693 os << '(';
00694
00695 for (Index i=0; i<Out().nelem(); ++i)
00696 {
00697 if (first) first=false;
00698 else os << ",";
00699
00700 os << Workspace::wsv_data[Out()[i]];
00701 }
00702
00703 for (Index i=0; i<In().nelem(); ++i)
00704 {
00705 if (first) first=false;
00706 else os << ",";
00707
00708 os << Workspace::wsv_data[In()[i]];
00709 }
00710
00711 os << ')';
00712 }
00713
00714 os << "{\n";
00715
00716 if ( 0 != Tasks().nelem() )
00717 {
00718 Tasks().print(os,indent+" ");
00719 }
00720
00721 os << indent << "}";
00722 }
00723
00725
00736 ostream& operator<<(ostream& os, const MRecord& a)
00737 {
00738 a.print(os,"");
00739 return os;
00740 }
00741