1 // Copyright (C) 2011 CEA/DEN, EDF R&D, OPEN CASCADE
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
19 // Authors : Guillaume Boulant (EDF) - 01/06/2011
21 #include "MEDCalculator_i.hxx"
22 #include "SALOME_KernelServices.hxx"
23 #include "Basics_Utils.hxx"
26 #include "MEDCouplingFieldDouble.hxx"
27 using namespace ParaMEDMEM;
29 MEDCalculator_i * MEDCalculator_i::_instance = NULL;
31 MEDCalculator_i * MEDCalculator_i::getInstance() {
32 if ( _instance == NULL ) {
33 _instance = new MEDCalculator_i();
38 MEDCalculator_i::MEDCalculator_i()
40 LOG("Creating a MEDCalculator_i instance");
41 _medDataManager = MEDDataManager_i::getInstance();
44 MEDCalculator_i::~MEDCalculator_i()
46 LOG("Deleting MEDCalculator_i instance");
50 * This function realizes the addition of the MEDCoupling field
51 * objects identified by the FieldHandler objects passed in arguments.
53 * It returns a FieldHandler that identifies the resulting MEDCoupling
54 * field object. The resulting MEDCoupling field object is physically
55 * in the SALOME MED container and is automatically registered in the
58 MEDOP::FieldHandler * MEDCalculator_i::add(const MEDOP::FieldHandler & f1_hdl,
59 const MEDOP::FieldHandler & f2_hdl)
61 // We first check that both operandes share the same mesh id. Note
62 // that it's not strictly required because the MEDCoupling operation
63 // would raise an exception if the fields does not share the same
65 if ( f1_hdl.meshid != f2_hdl.meshid ) {
67 std::string("ERROR: Mesh ids are different for the field operandes ") +
68 std::string(f1_hdl.fieldname) + std::string(" and ") + std::string(f2_hdl.fieldname);
69 throw KERNEL::createSalomeException(message.c_str());
72 MEDCouplingFieldDouble* f1 = _medDataManager->getFieldDouble(&f1_hdl);
73 MEDCouplingFieldDouble* f2 = _medDataManager->getFieldDouble(&f2_hdl);
75 MEDCouplingFieldDouble* field_result;
76 // This operation could raise an INTERP_KERNEL exception, for
77 // example, if the fields are not defined on the same support.
79 field_result = (*f1) + (*f2);
81 catch (INTERP_KERNEL::Exception &ex) {
82 throw KERNEL::createSalomeException(ex.what());
85 std::string name = std::string(f1->getName()) + "+" + std::string(f2->getName());
86 field_result->setName(name.c_str());
89 // The field must be registered in the dataManager structure so
90 // that it could be reused in a future operation (in particular for
91 // a manipulation that combine several operation as "r = f1+f2+f3",
92 // the operator will try to make the addition f1+f2 and then
93 // resultof(f1+f2) + f3. This last operation will fail if the field
94 // resultof(f1+f2) is not in the dataManager structure).
96 // Note that we choose arbitrary the first field operande to get the
97 // meshid (both have the same meshid).
99 long meshHandlerId = f1_hdl.meshid;
100 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
104 // _GBO_ We should test here if the iteration and order of the input
105 // files are identical for both operandes. A convention has to be
106 // defined here. By default, we let the iteration and order be
107 // determined by the resulting MEDCouplingFieldDouble instance (see
108 // function addField of the data manager).
111 return fieldResultHandler;
115 * This function realizes the substraction of the MEDCoupling field
116 * objects identified by the FieldHandler objects passed in arguments.
118 * It returns a FieldHandler that identifies the resulting MEDCoupling
119 * field object. The resulting MEDCoupling field object is physically
120 * in the SALOME MED container and is automatically registered in the
123 MEDOP::FieldHandler * MEDCalculator_i::sub(const MEDOP::FieldHandler & f1_hdl,
124 const MEDOP::FieldHandler & f2_hdl)
126 if ( f1_hdl.meshid != f2_hdl.meshid ) {
127 std::string message =
128 std::string("ERROR: Mesh ids are different for the field operandes ") +
129 std::string(f1_hdl.fieldname) + std::string(" and ") + std::string(f2_hdl.fieldname);
130 throw KERNEL::createSalomeException(message.c_str());
133 MEDCouplingFieldDouble* f1 = _medDataManager->getFieldDouble(&f1_hdl);
134 MEDCouplingFieldDouble* f2 = _medDataManager->getFieldDouble(&f2_hdl);
136 MEDCouplingFieldDouble* field_result;
138 field_result = (*f1) - (*f2);
140 catch (INTERP_KERNEL::Exception &ex) {
141 throw KERNEL::createSalomeException(ex.what());
144 std::string name = std::string(f1->getName()) + "-" + std::string(f2->getName());
145 field_result->setName(name.c_str());
147 long meshHandlerId = f1_hdl.meshid;
148 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
150 return fieldResultHandler;
154 * This function realizes the multiplication of the MEDCoupling field
155 * objects identified by the FieldHandler objects passed in arguments.
157 * It returns a FieldHandler that identifies the resulting MEDCoupling
158 * field object. The resulting MEDCoupling field object is physically
159 * in the SALOME MED container and is automatically registered in the
162 MEDOP::FieldHandler * MEDCalculator_i::mul(const MEDOP::FieldHandler & f1_hdl,
163 const MEDOP::FieldHandler & f2_hdl)
165 if ( f1_hdl.meshid != f2_hdl.meshid ) {
166 std::string message =
167 std::string("ERROR: Mesh ids are different for the field operandes ") +
168 std::string(f1_hdl.fieldname) + std::string(" and ") + std::string(f2_hdl.fieldname);
169 throw KERNEL::createSalomeException(message.c_str());
172 MEDCouplingFieldDouble* f1 = _medDataManager->getFieldDouble(&f1_hdl);
173 MEDCouplingFieldDouble* f2 = _medDataManager->getFieldDouble(&f2_hdl);
175 MEDCouplingFieldDouble* field_result;
177 field_result = (*f1) * (*f2);
179 catch (INTERP_KERNEL::Exception &ex) {
180 throw KERNEL::createSalomeException(ex.what());
182 std::string name = std::string(f1->getName()) + "*" + std::string(f2->getName());
183 field_result->setName(name.c_str());
185 long meshHandlerId = f1_hdl.meshid;
186 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
188 return fieldResultHandler;
192 * This function realizes the division of the MEDCoupling field
193 * objects identified by the FieldHandler objects passed in arguments.
195 * It returns a FieldHandler that identifies the resulting MEDCoupling
196 * field object. The resulting MEDCoupling field object is physically
197 * in the SALOME MED container and is automatically registered in the
200 MEDOP::FieldHandler * MEDCalculator_i::div(const MEDOP::FieldHandler & f1_hdl,
201 const MEDOP::FieldHandler & f2_hdl)
203 if ( f1_hdl.meshid != f2_hdl.meshid ) {
204 std::string message =
205 std::string("ERROR: Mesh ids are different for the field operandes ") +
206 std::string(f1_hdl.fieldname) + std::string(" and ") + std::string(f2_hdl.fieldname);
207 throw KERNEL::createSalomeException(message.c_str());
210 MEDCouplingFieldDouble* f1 = _medDataManager->getFieldDouble(&f1_hdl);
211 MEDCouplingFieldDouble* f2 = _medDataManager->getFieldDouble(&f2_hdl);
213 MEDCouplingFieldDouble* field_result;
215 field_result = (*f1) / (*f2);
217 catch (INTERP_KERNEL::Exception &ex) {
218 throw KERNEL::createSalomeException(ex.what());
221 std::string name = std::string(f1->getName()) + "/" + std::string(f2->getName());
222 field_result->setName(name.c_str());
224 long meshHandlerId = f1_hdl.meshid;
225 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
227 return fieldResultHandler;
231 * This function realizes the power of the MEDCoupling field
232 * object identified by the FieldHandler object passed in argument.
234 * It returns a FieldHandler that identifies the resulting MEDCoupling
235 * field object. The resulting MEDCoupling field object is physically
236 * in the SALOME MED container and is automatically registered in the
239 MEDOP::FieldHandler * MEDCalculator_i::pow(const MEDOP::FieldHandler & f_hdl, CORBA::Long power)
241 MEDCouplingFieldDouble* field = _medDataManager->getFieldDouble(&f_hdl);
243 // We use the applyFunc function to execute this operation. The
244 // applyFunc function modifies the original field (that is not what
245 // we want). So we have first to make a deep copy.
246 MEDCouplingFieldDouble* field_result;
248 field_result = field->clone(true);
249 string functionToApply = "u^"+ToString(power);
250 field_result->applyFunc(functionToApply.c_str());
252 catch (INTERP_KERNEL::Exception &ex) {
253 throw KERNEL::createSalomeException(ex.what());
256 // Set the name (the default is the same as the original field)
257 string name(field_result->getName());
259 name.append(ToString(power));
260 field_result->setName(name.c_str());
262 long meshHandlerId = f_hdl.meshid;
263 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
265 return fieldResultHandler;
269 * This function creates a new field as the linear transformation of
270 * the field object identified by the FieldHandler in argument. The
271 * transformation is y= factor*x + offset.
273 * It returns a FieldHandler that identifies the resulting MEDCoupling
274 * field object. The resulting MEDCoupling field object is physically
275 * in the SALOME MED container and is automatically registered in the
278 MEDOP::FieldHandler * MEDCalculator_i::lin(const MEDOP::FieldHandler & f_hdl, double factor, double offset)
280 MEDCouplingFieldDouble* field = _medDataManager->getFieldDouble(&f_hdl);
282 // We use the applyFunc function to execute this operation. The
283 // applyFunc function modifies the original field (that is not what
284 // we want). So we have first to make a deep copy.
285 MEDCouplingFieldDouble* field_result;
287 field_result = field->clone(true);
288 string functionToApply = "u*"+ToString(factor)+"+"+ToString(offset);
289 field_result->applyFunc(functionToApply.c_str());
291 catch (INTERP_KERNEL::Exception &ex) {
292 throw KERNEL::createSalomeException(ex.what());
295 // Set the name (the default is the same as the original field)
296 string name = string("lin(");
297 name.append(field->getName());
298 name.append(",factor=");
299 name.append(ToString(factor));
300 name.append(",offset=");
301 name.append(ToString(offset));
303 field_result->setName(name.c_str());
305 long meshHandlerId = f_hdl.meshid;
306 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
308 return fieldResultHandler;
313 * This function creates a new field as the duplicate of the field
314 * object identified by the FieldHandler in argument.
316 * It returns a FieldHandler that identifies the resulting MEDCoupling
317 * field object. The resulting MEDCoupling field object is physically
318 * in the SALOME MED container and is automatically registered in the
321 MEDOP::FieldHandler * MEDCalculator_i::dup(const MEDOP::FieldHandler & f_hdl)
323 MEDCouplingFieldDouble* field = _medDataManager->getFieldDouble(&f_hdl);
325 // We just make a deep copy of the input field
326 MEDCouplingFieldDouble* field_result;
328 field_result = field->clone(true);
330 catch (INTERP_KERNEL::Exception &ex) {
331 throw KERNEL::createSalomeException(ex.what());
334 // Set the name (the default is the same as the original field)
335 string name = string("dup(");
336 name.append(field->getName());
338 field_result->setName(name.c_str());
340 long meshHandlerId = f_hdl.meshid;
341 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
343 return fieldResultHandler;
347 * This creates a new field by applying a function on the specified
348 * field. The function is defined by a string of characters
349 * (function), that specifies the litteral equation to apply, and an
350 * integer (nbcomponents), that specifies the number of components to
351 * consider in the resulting field. This is to mimic the interface of
352 * MEDCouplingFieldDouble::applyFunc.
353 * Note that if nbcomponents is not in the range 1..N where N is the
354 * number of components of the specified field, then the function is
355 * apply on the whole field (as if specified N=numberOfComponents).
357 MEDOP::FieldHandler * MEDCalculator_i::fct(const MEDOP::FieldHandler & f_hdl,
358 const char * function, CORBA::Long nbResComponents)
360 MEDCouplingFieldDouble* field = _medDataManager->getFieldDouble(&f_hdl);
362 // We first make a deep copy of the input field
363 MEDCouplingFieldDouble* field_result;
365 field_result = field->clone(true);
366 if ( (nbResComponents == MEDOP::NBCOMP_DEFAULT ) ||
367 (nbResComponents < 1) || (nbResComponents > field_result->getNumberOfComponents()) ) {
368 field_result->applyFunc(function);
371 field_result->applyFunc(nbResComponents,function);
374 catch (INTERP_KERNEL::Exception &ex) {
375 throw KERNEL::createSalomeException(ex.what());
378 string name = string("fct("); name.append(field->getName());
379 name.append(",\""); name.append(function);
380 name.append(",\""); name.append(ToString(nbResComponents)); name.append("\")");
381 field_result->setName(name.c_str());
383 long meshHandlerId = f_hdl.meshid;
384 MEDOP::FieldHandler * fieldResultHandler = _medDataManager->addField(field_result,
386 return fieldResultHandler;