1 // Copyright (C) 2007-2015 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, or (at your option) any later version.
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 "MEDDataManager_i.hxx"
23 #include "SALOME_KernelServices.hxx"
24 #include "Basics_DirUtils.hxx"
25 #include "Basics_Utils.hxx"
27 #include "MEDLoader.hxx"
28 using namespace MEDCoupling;
34 MEDDataManager_i * MEDDataManager_i::_instance = NULL;
35 long MEDDataManager_i::LONG_UNDEFINED = -1;
37 MEDDataManager_i * MEDDataManager_i::getInstance() {
38 // _GBO_ we will certainly need to define one single DataManager per
39 // SALOME study and not one singleton for the whole session
40 if ( _instance == NULL ) {
41 _instance = new MEDDataManager_i();
46 #define IOR_UNDEF "IOR UNDEFINED"
47 MEDDataManager_i::MEDDataManager_i()
49 LOG("Creating a MEDDataManager_i instance");
53 _fieldseriesLastId = 0;
55 MEDDataManager_i::~MEDDataManager_i()
57 LOG("Deleting MEDDataManager_i instance");
60 std::string MEDDataManager_i::file_to_source(const char * filepath)
62 string source("file://");
63 source.append(filepath);
67 std::string MEDDataManager_i::source_to_file(const char * source)
69 string filepath(source);
70 filepath.replace(0,7,"");
75 * This function loads the meta-data from the specified med file and
76 * returns the associated datasource handler. The data source handler
77 * is a key to retrieve all informations concerning the data (meshes,
80 MEDCALC::DatasourceHandler * MEDDataManager_i::loadDatasource(const char *filepath) {
82 // We first check that this datasource is not already registered
83 long sourceid = getDatasourceId(filepath);
84 if ( sourceid != LONG_UNDEFINED ) {
85 // The file is already registered under the identifier sourceid
86 LOG("WRN: The file "<<filepath<<" is already registered with id="<<ToString(sourceid));
87 return new MEDCALC::DatasourceHandler(*_datasourceHandlerMap[sourceid]);
90 // Then we check that the file is readable by MEDLoader
91 CheckFileForRead(filepath);
93 // Initialise the datasource handler
94 MEDCALC::DatasourceHandler * datasourceHandler = new MEDCALC::DatasourceHandler();
95 datasourceHandler->id = _sourceLastId; _sourceLastId++;
96 datasourceHandler->name = (Kernel_Utils::GetBaseName(filepath)).c_str();
97 std::string tmp(file_to_source(filepath));
98 datasourceHandler->uri = CORBA::string_dup(tmp.c_str());
99 _datasourceHandlerMap[datasourceHandler->id] = datasourceHandler;
101 // We start by read the list of meshes (spatial supports of fields)
102 vector<string> meshNames = GetMeshNames(filepath);
103 int nbOfMeshes = meshNames.size();
104 for (int iMesh = 0; iMesh < nbOfMeshes; iMesh++) {
105 const char * meshName = meshNames[iMesh].c_str();
106 LOG("name of mesh " << iMesh << " = " << meshName);
108 MEDCALC::MeshHandler * meshHandler = new MEDCALC::MeshHandler();
109 meshHandler->id = _meshLastId; _meshLastId++;
110 meshHandler->name = meshName;
111 meshHandler->sourceid = datasourceHandler->id;
113 _meshHandlerMap[meshHandler->id] = meshHandler;
115 // For each mesh, we can read the list of the names of the
116 // associated fields, i.e. fields whose spatial support is this
118 vector<string> fieldNames = GetAllFieldNamesOnMesh(filepath,
120 int nbOfFields = fieldNames.size();
121 for (int iField = 0; iField < nbOfFields; iField++) {
122 const char * fieldName = fieldNames[iField].c_str();
123 LOG("-- name of field " << iField << " = " << fieldName);
125 // A field name could identify several MEDCoupling fields, that
126 // differ by their spatial discretization on the mesh (values on
127 // cells, values on nodes, ...). This spatial discretization is
128 // specified by the TypeOfField that is an integer value in this
135 // As a consequence, before loading values of a field, we have
136 // to determine the types of spatial discretization defined for
137 // this field and to chooose one.
139 vector<TypeOfField> listOfTypes = GetTypesOfField(filepath,
142 int nbOfTypes = listOfTypes.size();
143 for (int iType = 0; iType < nbOfTypes; iType++) {
144 LOG("---- type "<<iType<<" of field "<<iField<< " = " << listOfTypes[iType]);
146 // Then, we can get the iterations associated to this field on
147 // this type of spatial discretization:
148 std::vector< std::pair<int,int> > fieldIterations =
149 GetFieldIterations(listOfTypes[iType],
154 int nbFieldIterations = fieldIterations.size();
155 LOG("---- nb. iterations = " << nbFieldIterations);
157 // We can define the timeseries of fields (fieldseries) for
158 // this type. A fieldseries is a macro object that handle the whole
159 // set of time iterations of a field.
160 MEDCALC::FieldseriesHandler * fieldseriesHandler = new MEDCALC::FieldseriesHandler();
161 fieldseriesHandler->id = _fieldseriesLastId; _fieldseriesLastId++;
162 fieldseriesHandler->name = fieldName;
163 fieldseriesHandler->type = listOfTypes[iType];
164 fieldseriesHandler->meshid = meshHandler->id;
165 fieldseriesHandler->nbIter = nbFieldIterations;
166 _fieldseriesHandlerMap[fieldseriesHandler->id] = fieldseriesHandler;
168 // We can then load meta-data concerning all iterations
169 for (int iterationIdx=0; iterationIdx<nbFieldIterations; iterationIdx++) {
171 int iteration = fieldIterations[iterationIdx].first;
172 int order = fieldIterations[iterationIdx].second;
174 const char * source = datasourceHandler->uri;
175 MEDCALC::FieldHandler * fieldHandler = newFieldHandler(fieldName,
182 fieldHandler->meshid = meshHandler->id;
183 fieldHandler->fieldseriesId = fieldseriesHandler->id;
184 _fieldHandlerMap[fieldHandler->id] = fieldHandler;
190 return new MEDCALC::DatasourceHandler(*datasourceHandler);
193 long MEDDataManager_i::getDatasourceId(const char *filepath) {
194 std::string uri(file_to_source(filepath));
195 DatasourceHandlerMapIterator it = _datasourceHandlerMap.begin();
196 while ( it != _datasourceHandlerMap.end() ) {
197 if ( strcmp(it->second->uri,uri.c_str()) == 0 ) {
202 return LONG_UNDEFINED;
205 MEDCALC::DatasourceHandler*
206 MEDDataManager_i::getDatasourceHandler(const char *filepath)
208 std::string uri(file_to_source(filepath));
209 DatasourceHandlerMapIterator it = _datasourceHandlerMap.begin();
210 while ( it != _datasourceHandlerMap.end() ) {
211 if ( strcmp(it->second->uri,uri.c_str()) == 0 ) {
219 MEDCALC::DatasourceHandler*
220 MEDDataManager_i::getDatasourceHandlerFromID(CORBA::Long sourceid)
222 DatasourceHandlerMapIterator it = _datasourceHandlerMap.find(sourceid);
223 if (it != _datasourceHandlerMap.end())
230 MEDCALC::MeshHandler * MEDDataManager_i::getMesh(CORBA::Long meshId) {
231 if ( _meshHandlerMap.count(meshId) == 0 ) {
232 std::string message =
233 std::string("The mesh of id=") + ToString(meshId) +
234 std::string(" does not exist in the data manager");
236 throw KERNEL::createSalomeException(message.c_str());
238 return new MEDCALC::MeshHandler(*(_meshHandlerMap[meshId]));
243 * This function returns the list of mesh handlers associated to the
244 * specified datasource. It corresponds to the list ofmeshes defined
247 MEDCALC::MeshHandlerList * MEDDataManager_i::getMeshList(CORBA::Long datasourceId) {
249 // We initiate a list with the maximum lentgh
250 MEDCALC::MeshHandlerList_var meshHandlerList = new MEDCALC::MeshHandlerList();
251 meshHandlerList->length(_meshHandlerMap.size());
253 // Scan the map looking for meshes associated to the specified datasource
255 MeshHandlerMapIterator meshIt;
256 for ( meshIt=_meshHandlerMap.begin(); meshIt != _meshHandlerMap.end(); meshIt++) {
257 if ( meshIt->second->sourceid == datasourceId ) {
258 meshHandlerList[itemIdx] = *(meshIt->second);
263 // Adjust the length to the real number of elements
264 meshHandlerList->length(itemIdx);
265 return meshHandlerList._retn();
269 * This function returns the list of fieldseries defined on the
272 MEDCALC::FieldseriesHandlerList * MEDDataManager_i::getFieldseriesListOnMesh(CORBA::Long meshId) {
273 // We initiate a list with the maximum lentgh
274 MEDCALC::FieldseriesHandlerList_var
275 fieldseriesHandlerList = new MEDCALC::FieldseriesHandlerList();
276 fieldseriesHandlerList->length(_fieldseriesHandlerMap.size());
278 // Scan the map looking for fieldseries defined on the specified mesh
280 FieldseriesHandlerMapIterator it;
281 for ( it=_fieldseriesHandlerMap.begin(); it != _fieldseriesHandlerMap.end(); it++) {
282 if ( it->second->meshid == meshId ) {
283 fieldseriesHandlerList[itemIdx] = *(it->second);
288 // Adjust the length to the real number of elements
289 fieldseriesHandlerList->length(itemIdx);
290 return fieldseriesHandlerList._retn();
294 * A fieldseries is a timeseries of fields. Then the list of fields is
295 * the different time iterations defined for the specified field id.
297 MEDCALC::FieldHandlerList * MEDDataManager_i::getFieldListInFieldseries(CORBA::Long fieldseriesId) {
299 // We initiate a list with the maximum lentgh
300 MEDCALC::FieldHandlerList_var fieldHandlerList = new MEDCALC::FieldHandlerList();
301 fieldHandlerList->length(_fieldHandlerMap.size());
303 // Scan the map looking for field defined on the specified mesh
305 FieldHandlerMapIterator it;
306 for ( it=_fieldHandlerMap.begin(); it != _fieldHandlerMap.end(); it++) {
307 if ( it->second->fieldseriesId == fieldseriesId ) {
308 fieldHandlerList[itemIdx] = *(it->second);
313 // Adjust the length to the real number of elements
314 fieldHandlerList->length(itemIdx);
315 return fieldHandlerList._retn();
319 * This returns the whole set of fields handlers for all datasource
320 * that have been loaded using loadDatasource.
322 MEDCALC::FieldHandlerList * MEDDataManager_i::getFieldHandlerList() {
323 MEDCALC::FieldHandlerList_var fieldHandlerSeq = new MEDCALC::FieldHandlerList();
324 fieldHandlerSeq->length(_fieldHandlerMap.size());
327 FieldHandlerMapIterator fieldIt;
328 for ( fieldIt=_fieldHandlerMap.begin(); fieldIt != _fieldHandlerMap.end(); fieldIt++) {
329 fieldHandlerSeq[sequenceId] = *(fieldIt->second);
332 return fieldHandlerSeq._retn();
336 * This returns a copy of the fieldHandler associated to the specified id.
338 MEDCALC::FieldHandler * MEDDataManager_i::getFieldHandler(CORBA::Long fieldHandlerId) {
339 LOG("getFieldHandler: START")
341 FieldHandlerMapIterator fieldIt = _fieldHandlerMap.find(fieldHandlerId);
342 if ( fieldIt != _fieldHandlerMap.end() ) {
343 // >>> WARNING: CORBA struct specification indicates that the
344 // assignement acts as a desctructor for the structure that is
345 // pointed to. The values of the fields are copy first in the new
346 // structure that receives the assignement and finally the initial
347 // structure is destroyed. In the present case, WE WANT to keep
348 // the initial fieldHandler in the map. We must then make a deep
349 // copy of the structure found in the map and return the copy. The
350 // CORBA struct specification indicates that a deep copy can be
351 // done using the copy constructor. <<<
352 return new MEDCALC::FieldHandler(*(fieldIt->second));
358 * This returns a string representation of the field associated to the specified id.
360 char * MEDDataManager_i::getFieldRepresentation(CORBA::Long fieldHandlerId) {
361 LOG("getFieldRepresentation: START")
362 MEDCALC::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId);
363 MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler);
364 return CORBA::string_dup(fieldDouble->getArray()->repr().c_str());
367 void MEDDataManager_i::saveFields(const char * filepath,
368 const MEDCALC::FieldIdList & fieldIdList)
370 LOG("saveFields to : " << filepath);
372 // We first have to check if the target filepath is writable
373 // (segmentation fault in med otherwise)
374 if (!Kernel_Utils::IsWritable(Kernel_Utils::GetDirName(std::string(filepath)))) {
375 std::string message =
376 std::string("The target filepath ") +
377 std::string(filepath) +
378 std::string(" is not writable");
380 throw KERNEL::createSalomeException(message.c_str());
383 if ( fieldIdList.length() == 0 ) {
384 throw KERNEL::createSalomeException("No fields to save");
387 // Consider the first field to initiate the med file
388 CORBA::Long fieldHandlerId = fieldIdList[0];
389 MEDCALC::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId);
390 MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler);
393 bool writeFromScratch = true;
394 WriteField(filepath, fieldDouble, writeFromScratch);
396 writeFromScratch = false;
397 for(CORBA::ULong i=1; i<fieldIdList.length(); i++) {
398 fieldHandlerId = fieldIdList[i];
399 fieldHandler = getFieldHandler(fieldHandlerId);
400 fieldDouble = getFieldDouble(fieldHandler);
401 WriteField(filepath, fieldDouble, writeFromScratch);
404 catch (INTERP_KERNEL::Exception &ex) {
405 std::string message =
406 std::string("Error when saving file ") +
407 std::string(filepath) + std::string(" : ") + ex.what();
408 throw KERNEL::createSalomeException(message.c_str());
410 catch (const std::exception& ex) {
411 std::string message =
412 std::string("Error when saving file ") +
413 std::string(filepath) + std::string(" : ") + ex.what();
414 throw KERNEL::createSalomeException(message.c_str());
420 * This function must be used to indicate that the field with the
421 * specified id must be considered as persistent (if persistent is
422 * true) or not persistent (if persistent is false). If a field is
423 * marked as persistent, then it is automatically saved when the
424 * function savePersistentFields is called.
426 void MEDDataManager_i::markAsPersistent(CORBA::Long fieldHandlerId, bool persistent) {
427 LOG("mark as persistant : id="<<fieldHandlerId);
428 _fieldPersistencyMap[fieldHandlerId] = persistent;
431 void MEDDataManager_i::savePersistentFields(const char * filepath) {
432 LOG("savePersistentFields to : " << filepath);
433 std::vector<long> listId;
435 FieldPersistencyMapIterator mapIt;
436 for ( mapIt = _fieldPersistencyMap.begin(); mapIt != _fieldPersistencyMap.end(); mapIt++) {
437 if ( mapIt->second == true ) {
438 listId.push_back(mapIt->first);
442 MEDCALC::FieldIdList fieldIdList;
443 fieldIdList.length(listId.size());
444 for (int i=0; i<listId.size(); i++) {
445 fieldIdList[i] = CORBA::Long(listId[i]);
449 this->saveFields(filepath, fieldIdList);
451 catch (const SALOME::SALOME_Exception & ex) {
454 catch (const std::exception& ex) {
455 std::string message =
456 std::string("Error when saving file ") +
457 std::string(filepath) + std::string(" : ") + ex.what();
458 throw KERNEL::createSalomeException(message.c_str());
463 * This function is responsible for creating the FieldHandler
464 * instances. You must use this function because it manages
465 * automatically the identifier value (autoincrementation of a static
468 MEDCALC::FieldHandler * MEDDataManager_i::newFieldHandler(const char * fieldname,
469 const char * meshname,
475 MEDCALC::FieldHandler * fieldHandler = new MEDCALC::FieldHandler();
476 fieldHandler->id = _fieldLastId; _fieldLastId++;
477 fieldHandler->fieldname = fieldname;
478 fieldHandler->meshname = meshname;
479 fieldHandler->type = type;
480 fieldHandler->iteration = iteration;
481 fieldHandler->order = order;
482 fieldHandler->source = source;
487 * This updates the metadata of the field identified by its id with
488 * the data of the given field handler. Returns a copy of the updated
489 * handler (that should be identical to the given field handler for
490 * all data but not for the id that is an invariant for all session
492 * WARN: you should be warned that this function could leave the data
493 * model in a non-coherent state, by example if you change the mesh
494 * name while the mesh has not been updated.
496 MEDCALC::FieldHandler * MEDDataManager_i::updateFieldHandler(CORBA::Long fieldHandlerId,
497 const char * fieldname,
500 const char * source) {
501 FieldHandlerMapIterator fieldIt = _fieldHandlerMap.find(fieldHandlerId);
502 if ( fieldIt != _fieldHandlerMap.end() ) {
503 // Update the attributes
504 // >>> WARN: note that the id of a handler registered in the map
505 // SHOULD NEVER be modified because it is the identifier used in
506 // the whole application for this field all the session long.
508 fieldIt->second->fieldname = fieldname;
509 fieldIt->second->iteration = iteration;
510 fieldIt->second->order = order;
511 fieldIt->second->source = source;
513 return new MEDCALC::FieldHandler(*fieldIt->second);
518 MEDCouplingUMesh * MEDDataManager_i::getUMesh(long meshHandlerId) {
520 LOG("getUMesh: START")
522 MEDCouplingUMesh * myMesh = NULL;
523 if ( _meshMap.count(meshHandlerId) > 0 ) {
524 // The mesh has been found in the map
525 myMesh = _meshMap[meshHandlerId];
527 // The mesh is not loaded yet ==> load it and register it in the map
528 LOG("getUMesh: the mesh must be loaded. meshid="<<meshHandlerId);
529 if ( _meshHandlerMap[meshHandlerId] == NULL ) {
530 std::string message =
531 std::string("No mesh for id=") + ToString(meshHandlerId);
532 LOG("getUMesh: "<<message);
533 throw KERNEL::createSalomeException(message.c_str());
536 long sourceid = _meshHandlerMap[meshHandlerId]->sourceid;
537 std::string filepath(source_to_file((_datasourceHandlerMap[sourceid])->uri));
538 const char * meshName = _meshHandlerMap[meshHandlerId]->name;
539 int meshDimRelToMax = 0;
540 myMesh = ReadUMeshFromFile(filepath,meshName,meshDimRelToMax);
541 _meshMap[meshHandlerId] = myMesh;
547 * Try to retrieve the id of the specified mesh, i.e. the key it is
548 * registered with in the internal meshes map.
550 long MEDDataManager_i::getUMeshId(const MEDCouplingMesh * mesh) {
552 MeshMapIterator it = _meshMap.begin();
553 while ( it != _meshMap.end() ) {
554 found = (it->second == mesh);
560 return LONG_UNDEFINED;
564 * This method returns the physical data of the specified field,
565 * i.e. the MEDCoupling field associated to the specified field
566 * handler. If the field source is a file and the data ar not loaded
567 * yet, the this function load the data from the file in a MEDCoupling
568 * field instance. Otherwize, it just returns the MEDCoupling field
571 MEDCouplingFieldDouble * MEDDataManager_i::getFieldDouble(const MEDCALC::FieldHandler * fieldHandler)
574 LOG("getFieldDouble: START with id="<<fieldHandler->id);
576 if ( _fieldDoubleMap.count(fieldHandler->id) > 0 ) {
577 // The MEDCoupling field data are already loaded. Just return the
578 // reference of the MEDCouplingFieldDouble pointer
579 return _fieldDoubleMap[fieldHandler->id];
582 // The MEDCoupling field data are not loaded yet. Load the data and
583 // register the MEDCoupling field in our internal map an all the
584 // associated data if needed (i.e. the underlying mesh).
586 // At this step, the mesh handler needs a meshid correctly
587 // set. Normally, we should arrive at this step only in the case
588 // where the field is loaded from a file ==> the meshid is defined
589 // (see the loadDatasource function).
591 // >>>> __GBO__ TO BE CHECKED AND SERIOUSLY TESTED. There at least
592 // one case where we can arrive here with no previous call to
593 // loadDataSource: for example the field handler list can be obtained
594 // from a call to addFieldsFromFile instead of loadDataSource (see
595 // for exemple the getFieldRepresentation service of the
596 // dataManager, that comes here and then calls getUMesh where we
597 // need a map initialized only in loadDataSource) <<<<
598 long meshid = fieldHandler->meshid;
600 // We first have to check if the associated mesh is already loaded
601 // and to load it if needed. The loaded meshes are registered in a
602 // map whose key is the mesh handler id. This checking is
603 // automatically done by the function getUMesh. It's important to do
604 // it before the loading of field data to prevent from the case
605 // where the mesh would not have been loaded already (in the
606 // previous field loading).
607 MEDCouplingUMesh * myMesh =this->getUMesh(meshid);
609 long sourceid = _meshHandlerMap[meshid]->sourceid;
611 std::string filepath(source_to_file((_datasourceHandlerMap[sourceid])->uri));
612 std::string meshName(myMesh->getName());
613 LOG("getFieldDouble: field "<<fieldHandler->fieldname<<" loaded from file "<<filepath);
614 TypeOfField type = (TypeOfField)fieldHandler->type;
615 int meshDimRelToMax = 0;
616 MEDCouplingFieldDouble * myField = ReadField(type,
620 std::string(fieldHandler->fieldname),
621 fieldHandler->iteration,
622 fieldHandler->order);
623 myField->setMesh(myMesh);
624 _fieldDoubleMap[fieldHandler->id] = myField;
629 * This adds the specified MEDCoupling field in the collection managed
630 * by this DataManager. The associated FieldHandler is returned. This
631 * is typically used in a context where the MEDCoupling field is
632 * created from scratch, for example by operations in the
634 * @param[in] fieldDouble the MEDCouplingFieldDouble instance to add
635 * @param[in] meshHandlerId the id of the meshHandler this filed is associated to.
636 * @return a copy of the FieldHandler registered in the internal map for this field.
638 MEDCALC::FieldHandler * MEDDataManager_i::addField(MEDCouplingFieldDouble * fieldDouble,
641 std::string fieldName(fieldDouble->getName());
642 std::string meshName(fieldDouble->getMesh()->getName());
643 TypeOfField type = fieldDouble->getTypeOfField();
645 int iteration, order;
646 // WARN: note that the variables "iteration" and "order" are passed
647 // by reference to the function getTime (see documentation of
648 // MEDCouplingField). As a consequence, the values of these
649 // variables are updated by this function call. This is the mean to
650 // retrieve the iteration and order of the field.
651 double timestamp = fieldDouble->getTime(iteration, order);
653 // For the fields that are created in memory (by operations for
654 // example), the convention for the source attribute is to specify
655 // the fielddouble name, because this name describes the operation
656 // the field has been created with.
657 string * source = new string("mem://"); source->append(fieldName);
658 MEDCALC::FieldHandler * fieldHandler = newFieldHandler(fieldName.c_str(),
665 if ( meshHandlerId == LONG_UNDEFINED ) {
666 // We have to gess the id of the underlying mesh to preserve data
667 // integrity (a fieldHandler must have an attribute that contains
668 // the id of its underlying mesh):
670 // WARNING: it's better to let the client code (the one who calls the
671 // function addField) to specify this meshid. This guess procedure is
672 // not reliable, it's just to have a second chance.
674 LOG("addField: The mesh id is not defined. Trying to guess from the mesh name "<<meshName);
675 long meshid = this->getUMeshId(fieldDouble->getMesh());
676 fieldHandler->meshid = meshid;
677 if ( meshid == LONG_UNDEFINED ) {
678 // No mesh has been found in the internal map
679 LOG("addField: The mesh id for the mesh "<<meshName<<" can't be retrieved from the field "<<fieldName);
680 // _GBO_ : Maybe it could be better to raise an exception
684 fieldHandler->meshid = meshHandlerId;
687 _fieldHandlerMap[fieldHandler->id] = fieldHandler;
688 _fieldDoubleMap[fieldHandler->id] = fieldDouble;
689 // >>> WARNING: CORBA structure assignement specification ==> return
690 // >>> a deep copy to avoid the destruction of the fieldHandler
691 // >>> registered in the map (assignement acts as a destructor for
692 // >>> CORBA struct).
693 return new MEDCALC::FieldHandler(*fieldHandler);
697 * This function updates the meta-data "fieldname" associated to the
700 void MEDDataManager_i::updateFieldMetadata(CORBA::Long fieldHandlerId,
701 const char * fieldname,
702 CORBA::Long iteration,
706 // We have to update the field handler registered in the internal
707 // map AND the associated fieldDouble loaded in memory.
708 MEDCALC::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId);
709 updateFieldHandler(fieldHandlerId,fieldname,iteration,order,source);
711 MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler);
712 fieldDouble->setName(fieldname);
714 // _GBO_ TO BE IMPLEMENTED: iteration and order
718 * This can be used to associate to the specified field another mesh
719 * support than its current one. This is typically needed to operate 2
720 * fields defined on the same mesh but coming from different med
721 * files. In this case, the underlying meshes are different mesh
722 * objects (from the MEDCoupling point of view) and then no operation
723 * can be allowed by MEDCoupling. The operation of course fails if the
724 * new mesh is not identical to the old one.
726 void MEDDataManager_i::changeUnderlyingMesh(CORBA::Long fieldHandlerId, CORBA::Long meshHandlerId) {
728 MEDCALC::FieldHandler * fieldHandler = getFieldHandler(fieldHandlerId);
729 MEDCouplingFieldDouble* fieldDouble = getFieldDouble(fieldHandler);
730 MEDCouplingMesh * newMesh = getUMesh(meshHandlerId);
733 fieldDouble->changeUnderlyingMesh(newMesh,10,1e-12);
735 catch (INTERP_KERNEL::Exception &ex) {
736 std::string * message = new std::string("Error when changing the underlying mesh : ");
737 message->append(ex.what());
738 throw KERNEL::createSalomeException(message->c_str());
741 // The change of mesh is OK, then we can update the meta-data
742 _fieldHandlerMap[fieldHandlerId]->meshid = meshHandlerId;
743 _fieldHandlerMap[fieldHandlerId]->meshname = _meshHandlerMap[meshHandlerId]->name;
746 // WARN: if this field has already been request by the tui for
747 // manipulation (in a fieldproxy), then the data should be
751 INTERP_KERNEL::IntersectionType MEDDataManager_i::_getIntersectionType(const char* intersType) {
752 std::string type(intersType);
753 if (type == "Triangulation") {
754 return INTERP_KERNEL::Triangulation;
756 else if (type == "Convex") {
757 return INTERP_KERNEL::Convex;
759 else if (type == "Geometric2D") {
760 return INTERP_KERNEL::Geometric2D;
762 else if (type == "PointLocator") {
763 return INTERP_KERNEL::PointLocator;
765 else if (type == "Barycentric") {
766 return INTERP_KERNEL::Barycentric;
768 else if (type == "BarycentricGeo2D") {
769 return INTERP_KERNEL::BarycentricGeo2D;
772 std::string message("Error when trying to interpolate field: ");
773 message.append("Unrecognized intersection type: ");
774 message.append(type);
775 throw KERNEL::createSalomeException(message.c_str());
778 MEDCoupling::NatureOfField MEDDataManager_i::_getNatureOfField(const char* fieldNature) {
779 std::string nature(fieldNature);
780 if (nature == "NoNature") {
783 else if (nature == "ConservativeVolumic") {
784 return ConservativeVolumic;
786 else if (nature == "Integral") {
789 else if (nature == "IntegralGlobConstraint") {
790 return IntegralGlobConstraint;
792 else if (nature == "RevIntegral") {
796 std::string message("Error when trying to interpolate field: ");
797 message.append("Unrecognized field nature: ");
798 message.append(nature);
799 throw KERNEL::createSalomeException(message.c_str());
802 MEDCALC::FieldHandler* MEDDataManager_i::interpolateField(CORBA::Long fieldHandlerId, CORBA::Long meshHandlerId, const MEDCALC::InterpolationParameters& params) {
803 MEDCALC::FieldHandler* fieldHandler = getFieldHandler(fieldHandlerId);
804 MEDCouplingFieldDouble* sourceField = getFieldDouble(fieldHandler);
805 MEDCouplingMesh* sourceMesh = getUMesh(fieldHandler->meshid);
806 MEDCouplingMesh* targetMesh = getUMesh(meshHandlerId);
808 double precision = params.precision;
809 INTERP_KERNEL::IntersectionType interpType = this->_getIntersectionType(params.intersectionType);
810 std::string method(params.method);
811 double defaultValue = params.defaultValue;
812 bool reverse = params.reverse;
813 MEDCoupling::NatureOfField nature = this->_getNatureOfField(params.nature);
815 // 1. Build remapper between sourceMesh and targetMesh (compute interpolation matrix)
816 MEDCouplingRemapper remapper;
817 remapper.setPrecision(precision);
818 remapper.setIntersectionType(interpType);
819 remapper.prepare(sourceMesh, targetMesh, method.c_str());
821 // 2. Apply interpolation to the field
822 sourceField->setNature(nature);
823 MEDCouplingFieldDouble* targetField = NULL;
825 targetField = remapper.reverseTransferField(sourceField, defaultValue);
827 targetField = remapper.transferField(sourceField, defaultValue);
829 targetField->setMesh(targetMesh);
830 targetField->setName(targetMesh->getName() + "_field");
832 // 3. Create and register field handler
833 MEDCALC::FieldHandler* fieldResultHandler = this->addField(targetField, this->getUMeshId(targetField->getMesh()));
834 return fieldResultHandler;
840 * This functions display the internal data of the MEDDataManager on
841 * the server side (data in the SALOME container).
843 void MEDDataManager_i::serverlog() {
845 LOG("==== Field Handler Map ====================================================");
846 LOG("Size = "<<_fieldHandlerMap.size());
847 FieldHandlerMapIterator fhmIt;
848 for ( fhmIt = _fieldHandlerMap.begin(); fhmIt != _fieldHandlerMap.end(); fhmIt++) {
849 long id = fhmIt->first;
850 LOG("------------------------------------- id = "<<ToString(id));
851 LOG("- id \t= "<<fhmIt->second->id);
852 LOG("- fieldname \t= "<<fhmIt->second->fieldname);
853 LOG("- meshname \t= "<<fhmIt->second->meshname);
856 LOG("==== Field Double Map ====================================================");
857 LOG("Size = "<<_fieldDoubleMap.size());
858 FieldDoubleMapIterator fdmIt;
859 for ( fdmIt = _fieldDoubleMap.begin(); fdmIt != _fieldDoubleMap.end(); fdmIt++) {
860 long id = (*fdmIt).first;
861 MEDCouplingFieldDouble * fieldDouble = (*fdmIt).second;
862 LOG("------------------------------------- id = "<<ToString(id));
863 LOG("- fieldname \t= "<<fieldDouble->getName());
864 LOG("- meshname \t= "<<fieldDouble->getMesh()->getName());
869 * The event listener is created inside the GUI by the
870 * WorkspaceController. This function is called by the WorkspaceController to
871 * store the event listener IOR for the time of the session. Then this
872 * IOR can be available to any point of the application that can
873 * request the data manager (the python console for example).
875 void MEDDataManager_i::setEventListenerIOR(const char * ior) {
876 _medEventListenerIOR = ior;
879 * Return the IOR of the event listener that resides in the
880 * GUI. Having the IOR, you can restore the CORBA object by using:
882 * In a python SALOME context:
885 * >>> salome.salome_init()
886 * >>> myobject = salome.orb.string_to_object(ior)
888 * In a C++ SALOME context: (to do if needed)
890 char * MEDDataManager_i::getEventListenerIOR() {
891 if ( _medEventListenerIOR == "" ) {
892 throw KERNEL::createSalomeException("The event listener IOR is not defined");
894 // WARN: return a copy because the pointer memory will be released
895 // (CORBA specification)
896 return CORBA::string_dup( _medEventListenerIOR.c_str() );