1 // Copyright (C) 2011-2013 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // Authors : Guillaume Boulant (EDF) - 01/06/2011
22 #include "MEDCalculator_i.hxx"
23 #include "SALOME_KernelServices.hxx"
24 #include "Basics_Utils.hxx"
27 #include "MEDCouplingFieldDouble.hxx"
28 using namespace ParaMEDMEM;
30 MEDCalculator_i * MEDCalculator_i::_instance = NULL;
32 MEDCalculator_i * MEDCalculator_i::getInstance() {
33 if ( _instance == NULL ) {
34 _instance = new MEDCalculator_i();
39 MEDCalculator_i::MEDCalculator_i()
41 LOG("Creating a MEDCalculator_i instance");
42 _medDataManager = MEDDataManager_i::getInstance();
45 MEDCalculator_i::~MEDCalculator_i()
47 LOG("Deleting MEDCalculator_i instance");
51 * This function realizes the addition of the MEDCoupling field
52 * objects identified by the FieldHandler objects passed in arguments.
54 * It returns a FieldHandler that identifies the resulting MEDCoupling
55 * field object. The resulting MEDCoupling field object is physically
56 * in the SALOME MED container and is automatically registered in the
59 MEDOP::FieldHandler * MEDCalculator_i::add(const MEDOP::FieldHandler & f1_hdl,
60 const MEDOP::FieldHandler & f2_hdl)
62 // We first check that both operandes share the same mesh id. Note
63 // that it's not strictly required because the MEDCoupling operation
64 // would raise an exception if the fields does not share the same
66 if ( f1_hdl.meshid != f2_hdl.meshid ) {
68 std::string("ERROR: Mesh ids are different for the field operandes ") +
69 std::string(f1_hdl.fieldname) + std::string(" and ") + std::string(f2_hdl.fieldname);
70 throw KERNEL::createSalomeException(message.c_str());
73 MEDCouplingFieldDouble* f1 = _medDataManager->getFieldDouble(&f1_hdl);
74 MEDCouplingFieldDouble* f2 = _medDataManager->getFieldDouble(&f2_hdl);
76 MEDCouplingFieldDouble* field_result;
77 // This operation could raise an INTERP_KERNEL exception, for
78 // example, if the fields are not defined on the same support.
80 field_result = (*f1) + (*f2);
82 catch (INTERP_KERNEL::Exception &ex) {
83 throw KERNEL::createSalomeException(ex.what());
86 std::string name = std::string(f1->getName()) + "+" + std::string(f2->getName());
87 field_result->setName(name.c_str());
90 // The field must be registered in the dataManager structure so
91 // that it could be reused in a future operation (in particular for
92 // a manipulation that combine several operation as "r = f1+f2+f3",
93 // the operator will try to make the addition f1+f2 and then
94 // resultof(f1+f2) + f3. This last operation will fail if the field
95 // resultof(f1+f2) is not in the dataManager structure).
97 // Note that we choose arbitrary the first field operande to get the
98 // meshid (both have the same meshid).
100 long meshHandlerId = f1_hdl.meshid;
101 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
105 // _GBO_ We should test here if the iteration and order of the input
106 // files are identical for both operandes. A convention has to be
107 // defined here. By default, we let the iteration and order be
108 // determined by the resulting MEDCouplingFieldDouble instance (see
109 // function addField of the data manager).
112 return fieldResultHandler;
116 * This function realizes the substraction of the MEDCoupling field
117 * objects identified by the FieldHandler objects passed in arguments.
119 * It returns a FieldHandler that identifies the resulting MEDCoupling
120 * field object. The resulting MEDCoupling field object is physically
121 * in the SALOME MED container and is automatically registered in the
124 MEDOP::FieldHandler * MEDCalculator_i::sub(const MEDOP::FieldHandler & f1_hdl,
125 const MEDOP::FieldHandler & f2_hdl)
127 if ( f1_hdl.meshid != f2_hdl.meshid ) {
128 std::string message =
129 std::string("ERROR: Mesh ids are different for the field operandes ") +
130 std::string(f1_hdl.fieldname) + std::string(" and ") + std::string(f2_hdl.fieldname);
131 throw KERNEL::createSalomeException(message.c_str());
134 MEDCouplingFieldDouble* f1 = _medDataManager->getFieldDouble(&f1_hdl);
135 MEDCouplingFieldDouble* f2 = _medDataManager->getFieldDouble(&f2_hdl);
137 MEDCouplingFieldDouble* field_result;
139 field_result = (*f1) - (*f2);
141 catch (INTERP_KERNEL::Exception &ex) {
142 throw KERNEL::createSalomeException(ex.what());
145 std::string name = std::string(f1->getName()) + "-" + std::string(f2->getName());
146 field_result->setName(name.c_str());
148 long meshHandlerId = f1_hdl.meshid;
149 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
151 return fieldResultHandler;
155 * This function realizes the multiplication of the MEDCoupling field
156 * objects identified by the FieldHandler objects passed in arguments.
158 * It returns a FieldHandler that identifies the resulting MEDCoupling
159 * field object. The resulting MEDCoupling field object is physically
160 * in the SALOME MED container and is automatically registered in the
163 MEDOP::FieldHandler * MEDCalculator_i::mul(const MEDOP::FieldHandler & f1_hdl,
164 const MEDOP::FieldHandler & f2_hdl)
166 if ( f1_hdl.meshid != f2_hdl.meshid ) {
167 std::string message =
168 std::string("ERROR: Mesh ids are different for the field operandes ") +
169 std::string(f1_hdl.fieldname) + std::string(" and ") + std::string(f2_hdl.fieldname);
170 throw KERNEL::createSalomeException(message.c_str());
173 MEDCouplingFieldDouble* f1 = _medDataManager->getFieldDouble(&f1_hdl);
174 MEDCouplingFieldDouble* f2 = _medDataManager->getFieldDouble(&f2_hdl);
176 MEDCouplingFieldDouble* field_result;
178 field_result = (*f1) * (*f2);
180 catch (INTERP_KERNEL::Exception &ex) {
181 throw KERNEL::createSalomeException(ex.what());
183 std::string name = std::string(f1->getName()) + "*" + std::string(f2->getName());
184 field_result->setName(name.c_str());
186 long meshHandlerId = f1_hdl.meshid;
187 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
189 return fieldResultHandler;
193 * This function realizes the division of the MEDCoupling field
194 * objects identified by the FieldHandler objects passed in arguments.
196 * It returns a FieldHandler that identifies the resulting MEDCoupling
197 * field object. The resulting MEDCoupling field object is physically
198 * in the SALOME MED container and is automatically registered in the
201 MEDOP::FieldHandler * MEDCalculator_i::div(const MEDOP::FieldHandler & f1_hdl,
202 const MEDOP::FieldHandler & f2_hdl)
204 if ( f1_hdl.meshid != f2_hdl.meshid ) {
205 std::string message =
206 std::string("ERROR: Mesh ids are different for the field operandes ") +
207 std::string(f1_hdl.fieldname) + std::string(" and ") + std::string(f2_hdl.fieldname);
208 throw KERNEL::createSalomeException(message.c_str());
211 MEDCouplingFieldDouble* f1 = _medDataManager->getFieldDouble(&f1_hdl);
212 MEDCouplingFieldDouble* f2 = _medDataManager->getFieldDouble(&f2_hdl);
214 MEDCouplingFieldDouble* field_result;
216 field_result = (*f1) / (*f2);
218 catch (INTERP_KERNEL::Exception &ex) {
219 throw KERNEL::createSalomeException(ex.what());
222 std::string name = std::string(f1->getName()) + "/" + std::string(f2->getName());
223 field_result->setName(name.c_str());
225 long meshHandlerId = f1_hdl.meshid;
226 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
228 return fieldResultHandler;
232 * This function realizes the power of the MEDCoupling field
233 * object identified by the FieldHandler object passed in argument.
235 * It returns a FieldHandler that identifies the resulting MEDCoupling
236 * field object. The resulting MEDCoupling field object is physically
237 * in the SALOME MED container and is automatically registered in the
240 MEDOP::FieldHandler * MEDCalculator_i::pow(const MEDOP::FieldHandler & f_hdl, CORBA::Long power)
242 MEDCouplingFieldDouble* field = _medDataManager->getFieldDouble(&f_hdl);
244 // We use the applyFunc function to execute this operation. The
245 // applyFunc function modifies the original field (that is not what
246 // we want). So we have first to make a deep copy.
247 MEDCouplingFieldDouble* field_result;
249 field_result = field->clone(true);
250 string functionToApply = "u^"+ToString(power);
251 field_result->applyFunc(functionToApply.c_str());
253 catch (INTERP_KERNEL::Exception &ex) {
254 throw KERNEL::createSalomeException(ex.what());
257 // Set the name (the default is the same as the original field)
258 string name(field_result->getName());
260 name.append(ToString(power));
261 field_result->setName(name.c_str());
263 long meshHandlerId = f_hdl.meshid;
264 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
266 return fieldResultHandler;
270 * This function creates a new field as the linear transformation of
271 * the field object identified by the FieldHandler in argument. The
272 * transformation is y= factor*x + offset.
274 * It returns a FieldHandler that identifies the resulting MEDCoupling
275 * field object. The resulting MEDCoupling field object is physically
276 * in the SALOME MED container and is automatically registered in the
279 MEDOP::FieldHandler * MEDCalculator_i::lin(const MEDOP::FieldHandler & f_hdl, double factor, double offset)
281 MEDCouplingFieldDouble* field = _medDataManager->getFieldDouble(&f_hdl);
283 // We use the applyFunc function to execute this operation. The
284 // applyFunc function modifies the original field (that is not what
285 // we want). So we have first to make a deep copy.
286 MEDCouplingFieldDouble* field_result;
288 field_result = field->clone(true);
289 string functionToApply = "u*"+ToString(factor)+"+"+ToString(offset);
290 field_result->applyFunc(functionToApply.c_str());
292 catch (INTERP_KERNEL::Exception &ex) {
293 throw KERNEL::createSalomeException(ex.what());
296 // Set the name (the default is the same as the original field)
297 string name = string("lin(");
298 name.append(field->getName());
299 name.append(",factor=");
300 name.append(ToString(factor));
301 name.append(",offset=");
302 name.append(ToString(offset));
304 field_result->setName(name.c_str());
306 long meshHandlerId = f_hdl.meshid;
307 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
309 return fieldResultHandler;
314 * This function creates a new field as the duplicate of the field
315 * object identified by the FieldHandler in argument.
317 * It returns a FieldHandler that identifies the resulting MEDCoupling
318 * field object. The resulting MEDCoupling field object is physically
319 * in the SALOME MED container and is automatically registered in the
322 MEDOP::FieldHandler * MEDCalculator_i::dup(const MEDOP::FieldHandler & f_hdl)
324 MEDCouplingFieldDouble* field = _medDataManager->getFieldDouble(&f_hdl);
326 // We just make a deep copy of the input field
327 MEDCouplingFieldDouble* field_result;
329 field_result = field->clone(true);
331 catch (INTERP_KERNEL::Exception &ex) {
332 throw KERNEL::createSalomeException(ex.what());
335 // Set the name (the default is the same as the original field)
336 string name = string("dup(");
337 name.append(field->getName());
339 field_result->setName(name.c_str());
341 long meshHandlerId = f_hdl.meshid;
342 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
344 return fieldResultHandler;
348 * This creates a new field by applying a function on the specified
349 * field. The function is defined by a string of characters
350 * (function), that specifies the litteral equation to apply, and an
351 * integer (nbcomponents), that specifies the number of components to
352 * consider in the resulting field. This is to mimic the interface of
353 * MEDCouplingFieldDouble::applyFunc.
354 * Note that if nbcomponents is not in the range 1..N where N is the
355 * number of components of the specified field, then the function is
356 * apply on the whole field (as if specified N=numberOfComponents).
358 MEDOP::FieldHandler * MEDCalculator_i::fct(const MEDOP::FieldHandler & f_hdl,
359 const char * function, CORBA::Long nbResComponents)
361 MEDCouplingFieldDouble* field = _medDataManager->getFieldDouble(&f_hdl);
363 // We first make a deep copy of the input field
364 MEDCouplingFieldDouble* field_result;
366 field_result = field->clone(true);
367 if ( (nbResComponents == MEDOP::NBCOMP_DEFAULT ) ||
368 (nbResComponents < 1) || (nbResComponents > field_result->getNumberOfComponents()) ) {
369 field_result->applyFunc(function);
372 field_result->applyFunc(nbResComponents,function);
375 catch (INTERP_KERNEL::Exception &ex) {
376 throw KERNEL::createSalomeException(ex.what());
379 string name = string("fct("); name.append(field->getName());
380 name.append(",\""); name.append(function);
381 name.append(",\""); name.append(ToString(nbResComponents)); name.append("\")");
382 field_result->setName(name.c_str());
384 long meshHandlerId = f_hdl.meshid;
385 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
387 return fieldResultHandler;