preCICE v3.2.0
Loading...
Searching...
No Matches
ActionConfiguration.cpp
Go to the documentation of this file.
2#include <algorithm>
3#include <memory>
4#include <ostream>
5#include <stdexcept>
6#include <utility>
7
12#include "logging/LogMacros.hpp"
13#include "mesh/Data.hpp"
14#include "mesh/Mesh.hpp"
16#include "utils/assertion.hpp"
17#include "xml/ConfigParser.hpp"
18#include "xml/XMLAttribute.hpp"
19
20namespace precice::action {
21
23 xml::XMLTag &parent,
25 : NAME_DIVIDE_BY_AREA("divide-by-area"),
26 NAME_MULTIPLY_BY_AREA("multiply-by-area"),
27 NAME_SUMMATION("summation"),
28 NAME_PYTHON("python"),
29 NAME_RECORDER("recorder"),
30 TAG_SOURCE_DATA("source-data"),
31 TAG_TARGET_DATA("target-data"),
32 TAG_CONVERGENCE_TOLERANCE("convergence-tolerance"),
33 TAG_MAX_ITERATIONS("max-iterations"),
34 TAG_MODULE_PATH("path"),
35 TAG_MODULE_NAME("module"),
36 WRITE_MAPPING_POST("write-mapping-post"),
37 READ_MAPPING_POST("read-mapping-post"),
38 _meshConfig(std::move(meshConfig))
39{
40 using namespace xml;
41 XMLTag tagSourceData(*this, TAG_SOURCE_DATA, XMLTag::OCCUR_ONCE);
42 tagSourceData.setDocumentation("Single data to read from. ");
43 XMLTag tagMultipleSourceData(*this, TAG_SOURCE_DATA, XMLTag::OCCUR_ONCE_OR_MORE);
44 tagMultipleSourceData.setDocumentation("Multiple data to read from.");
45 XMLTag tagTargetData(*this, TAG_TARGET_DATA, XMLTag::OCCUR_ONCE);
46 tagTargetData.setDocumentation("Data to read from and write to.");
47
48 auto attrName = XMLAttribute<std::string>(ATTR_NAME).setDocumentation("Name of the data.");
49 tagSourceData.addAttribute(attrName);
50 tagMultipleSourceData.addAttribute(attrName);
51 tagTargetData.addAttribute(attrName);
52
54 XMLTag::Occurrence occ = XMLTag::OCCUR_ARBITRARY;
55 {
56 XMLTag tag(*this, NAME_MULTIPLY_BY_AREA, occ, TAG);
57 tag.setDocumentation("Multiplies data values with mesh area associated to vertex holding the value.");
58 tag.addSubtag(tagTargetData);
59 tags.push_back(tag);
60 }
61 {
62 XMLTag tag(*this, NAME_DIVIDE_BY_AREA, occ, TAG);
63 tag.setDocumentation("Divides data values by mesh area associated to vertex holding the value.");
64 tag.addSubtag(tagTargetData);
65 tags.push_back(tag);
66 }
67 {
68 XMLTag tag(*this, NAME_SUMMATION, occ, TAG);
69 tag.setDocumentation("Sums up multiple source data values and writes the result into target data.");
70 tag.addSubtag(tagMultipleSourceData);
71 tag.addSubtag(tagTargetData);
72 tags.push_back(tag);
73 }
74 {
75 XMLTag tag(*this, NAME_RECORDER, occ, TAG);
76 tag.setDocumentation("Records action invocations for testing purposes.");
77 tags.push_back(tag);
78 }
79 {
80 XMLTag tag(*this, NAME_PYTHON, occ, TAG);
81 tag.setDocumentation("Calls Python script to execute action."
82 " See preCICE file \"src/action/PythonAction.py\" for an example.");
83
84 XMLTag tagModulePath(*this, TAG_MODULE_PATH, XMLTag::OCCUR_NOT_OR_ONCE);
85 tagModulePath.setDocumentation("Directory path to Python module, i.e. script file."
86 " If it doesn't occur, the current path is used");
87 tagModulePath.addAttribute(makeXMLAttribute(ATTR_NAME, "").setDocumentation("The path to the directory of the module."));
88 tag.addSubtag(tagModulePath);
89
90 XMLTag tagModule(*this, TAG_MODULE_NAME, XMLTag::OCCUR_ONCE);
91 tagModule.setDocumentation("Name of Python module, i.e. Python script file without file ending. "
92 "The module name has to differ from existing (library) modules, "
93 "otherwise, the existing module will be loaded instead of the user script.");
94 tagModule.addAttribute(attrName);
95 tag.addSubtag(tagModule);
96
97 XMLTag tagOptionalSourceData(*this, TAG_SOURCE_DATA, XMLTag::OCCUR_NOT_OR_ONCE);
98 tagOptionalSourceData.setDocumentation("Source data to be read is handed to the Python module."
99 " Can be omitted, if only a target data is needed.");
100 tagOptionalSourceData.addAttribute(attrName);
101 tag.addSubtag(tagOptionalSourceData);
102
103 XMLTag tagOptionalTargetData(*this, TAG_TARGET_DATA, XMLTag::OCCUR_NOT_OR_ONCE);
104 tagOptionalTargetData.setDocumentation("Target data to be read and written to is handed to the Python module."
105 " Can be omitted, if only source data is needed.");
106 tagOptionalTargetData.addAttribute(attrName);
107 tag.addSubtag(tagOptionalTargetData);
108
109 tags.push_back(tag);
110 }
111
112 auto attrTiming = XMLAttribute<std::string>(ATTR_TIMING)
113 .setDocumentation("Determines when (relative to advancing the coupling scheme and the data mappings) the action is executed.")
115
116 auto attrMesh = XMLAttribute<std::string>(ATTR_MESH)
117 .setDocumentation("Determines mesh used in action.");
118 for (XMLTag &tag : tags) {
119 tag.addAttribute(attrTiming);
120 tag.addAttribute(attrMesh);
121 parent.addSubtag(tag);
122 }
123}
124
126 const xml::ConfigurationContext &context,
127 xml::XMLTag &callingTag)
128{
129 PRECICE_TRACE(callingTag.getName());
130 if (callingTag.getNamespace() == TAG) {
132 _configuredAction.type = callingTag.getName();
135 // addSubtags ( callingTag, _configured.type );
136 } else if (callingTag.getName() == TAG_SOURCE_DATA) {
137 _configuredAction.sourceDataVector.push_back(callingTag.getStringAttributeValue(ATTR_NAME));
138 } else if (callingTag.getName() == TAG_TARGET_DATA) {
139 _configuredAction.targetData = callingTag.getStringAttributeValue(ATTR_NAME);
140 } else if (callingTag.getName() == TAG_CONVERGENCE_TOLERANCE) {
141 _configuredAction.convergenceTolerance =
143 } else if (callingTag.getName() == TAG_MAX_ITERATIONS) {
144 _configuredAction.maxIterations = callingTag.getIntAttributeValue(ATTR_VALUE);
145 } else if (callingTag.getName() == TAG_MODULE_PATH) {
147 } else if (callingTag.getName() == TAG_MODULE_NAME) {
149 }
150}
151
153 const xml::ConfigurationContext &context,
154 xml::XMLTag &callingTag)
155{
156 if (callingTag.getNamespace() == TAG) {
157 createAction();
158 }
159}
160
162{
163 PRECICE_CHECK(_meshConfig->hasMeshName(_configuredAction.mesh), "No mesh name \"{}\" found. Please check that the correct mesh name is used.", _configuredAction.mesh);
164 return _meshConfig->getMesh(_configuredAction.mesh)->getID();
165}
166
168{
170
173
174 // Determine data and mesh
175 std::vector<int> sourceDataIDs;
176 int targetDataID = -1;
178 "Data action uses mesh \"{}\" which is not configured. Please ensure that the correct mesh name is given in <action:python mesh=\"...\">", _configuredAction.mesh);
180
181 if (!_configuredAction.targetData.empty()) {
182 PRECICE_CHECK(mesh->hasDataName(_configuredAction.targetData),
183 "Data action uses target data \"{}\" which is not configured. Please ensure that the target data name is used by the mesh with name \"{}\".", _configuredAction.targetData, _configuredAction.mesh);
184 targetDataID = mesh->data(_configuredAction.targetData)->getID();
185 PRECICE_ASSERT(targetDataID != -1);
186 }
187
188 for (const std::string &dataName : _configuredAction.sourceDataVector) {
189 PRECICE_CHECK(mesh->hasDataName(dataName), "Data action uses source data \"{}\" which is not configured. Please ensure that the target data name is used by the mesh with name \"{}\".", dataName, _configuredAction.mesh);
190 sourceDataIDs.push_back(mesh->data(dataName)->getID());
191 }
192
193 PRECICE_CHECK((_configuredAction.sourceDataVector.empty() || not sourceDataIDs.empty()),
194 "Data action uses source data \"{}\" which is not configured. Please ensure that the source data name is used by the mesh with name \"{}\".", _configuredAction.sourceDataVector.back(), _configuredAction.mesh);
195
199 new action::ScaleByAreaAction(timing, targetDataID,
201 } else if (_configuredAction.type == NAME_DIVIDE_BY_AREA) {
203 new action::ScaleByAreaAction(timing, targetDataID,
205 } else if (_configuredAction.type == NAME_SUMMATION) {
207 new action::SummationAction(timing, sourceDataIDs, targetDataID, mesh));
208 } else if (_configuredAction.type == NAME_RECORDER) {
210 new action::RecorderAction(timing, mesh));
211 }
212#ifndef PRECICE_NO_PYTHON
213 else if (_configuredAction.type == NAME_PYTHON) {
216 mesh, targetDataID, sourceDataIDs.back()));
217 }
218#endif
219 PRECICE_ASSERT(action.get() != nullptr);
220 _actions.push_back(std::move(action));
221}
222
224{
229 } else if (_configuredAction.timing == READ_MAPPING_POST) {
231 } else {
232 PRECICE_ERROR("Unknown action timing \"{}\". "
233 "Valid action timings are read-mapping-post and write-mapping-post.",
234 _configuredAction.timing);
235 }
236 return timing;
237}
238
239} // namespace precice::action
#define PRECICE_ERROR(...)
Definition LogMacros.hpp:16
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_CHECK(check,...)
Definition LogMacros.hpp:32
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
T back(T... args)
void createAction()
Adds all required subtags to the main action tag.
void xmlTagCallback(const xml::ConfigurationContext &context, xml::XMLTag &callingTag) override
Callback function required for use of automatic configuration.
ActionConfiguration(xml::XMLTag &parent, mesh::PtrMeshConfiguration meshConfig)
void xmlEndTagCallback(const xml::ConfigurationContext &context, xml::XMLTag &callingTag) override
Callback function required for use of automatic configuration.
int getUsedMeshID() const
Returns the id of the mesh used in the data action.
Timing
Defines the time and place of application of the action.
Definition Action.hpp:17
Action whose implementation is given in a Python file.
Action that records invocations for testing purposes.
@ SCALING_MULTIPLY_BY_AREA
Multiplies the data by the area of neighboring edges/triangles.
@ SCALING_DIVIDE_BY_AREA
Divides the data by the area of neighboring edges/triangles.
Action that adds multiple source data into target data.
Represents an XML tag to be configured automatically.
Definition XMLTag.hpp:28
const std::string & getNamespace() const
Returns xml namespace.
Definition XMLTag.hpp:159
std::string getStringAttributeValue(const std::string &name, std::optional< std::string > default_value=std::nullopt) const
Definition XMLTag.cpp:145
const std::string & getName() const
Returns name (without namespace).
Definition XMLTag.hpp:153
int getIntAttributeValue(const std::string &name, std::optional< int > default_value=std::nullopt) const
Definition XMLTag.cpp:131
double getDoubleAttributeValue(const std::string &name, std::optional< double > default_value=std::nullopt) const
Definition XMLTag.cpp:117
XMLTag & addSubtag(const XMLTag &tag)
Adds an XML tag as subtag by making a copy of the given tag.
Definition XMLTag.cpp:41
T empty(T... args)
contains actions to modify exchanged data.
Definition Action.hpp:6
std::unique_ptr< Action > PtrAction
provides Mesh, Data and primitives.
std::shared_ptr< Mesh > PtrMesh
std::shared_ptr< MeshConfiguration > PtrMeshConfiguration
contains the XML configuration parser.
STL namespace.
T push_back(T... args)
Stores configuration information temporarily to create the Action.
Tightly coupled to the parameters of Participant()
Definition XMLTag.hpp:21