1 2 #include <engine.h> /* Matlab include file */ 3 #include <petscsys.h> 4 #include <petscmatlab.h> /*I "petscmatlab.h" I*/ 5 #include <petsc/private/petscimpl.h> 6 7 struct _p_PetscMatlabEngine { 8 PETSCHEADER(int); 9 Engine *ep; 10 char buffer[1024]; 11 }; 12 13 PetscClassId MATLABENGINE_CLASSID = -1; 14 15 /*@C 16 PetscMatlabEngineCreate - Creates a MATLAB engine object 17 18 Not Collective 19 20 Input Parameters: 21 + comm - a separate MATLAB engine is started for each process in the communicator 22 - machine - name of machine where MATLAB engine is to be run (usually NULL) 23 24 Output Parameter: 25 . mengine - the resulting object 26 27 Options Database: 28 . -matlab_engine_graphics - allow the MATLAB engine to display graphics 29 30 Level: advanced 31 32 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 33 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 34 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 35 @*/ 36 PetscErrorCode PetscMatlabEngineCreate(MPI_Comm comm,const char machine[],PetscMatlabEngine *mengine) 37 { 38 PetscErrorCode ierr; 39 PetscMPIInt rank,size; 40 char buffer[256]; 41 PetscMatlabEngine e; 42 PetscBool flg = PETSC_FALSE; 43 44 PetscFunctionBegin; 45 if (MATLABENGINE_CLASSID == -1) { 46 ierr = PetscClassIdRegister("MATLAB Engine",&MATLABENGINE_CLASSID);CHKERRQ(ierr); 47 } 48 ierr = PetscOptionsGetBool(NULL,NULL,"-matlab_engine_graphics",&flg,NULL);CHKERRQ(ierr); 49 50 ierr = PetscHeaderCreate(e,MATLABENGINE_CLASSID,"MatlabEngine","MATLAB Engine","Sys",comm,PetscMatlabEngineDestroy,NULL);CHKERRQ(ierr); 51 52 if (!machine) machine = "\0"; 53 ierr = PetscStrncpy(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));CHKERRQ(ierr); 54 if (!flg) { 55 ierr = PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));CHKERRQ(ierr); 56 } 57 ierr = PetscStrlcat(buffer," -nojvm ",sizeof(buffer));CHKERRQ(ierr); 58 ierr = PetscInfo2(0,"Starting MATLAB engine on %s with command %s\n",machine,buffer);CHKERRQ(ierr); 59 e->ep = engOpen(buffer); 60 if (!e->ep) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start MATLAB engine on %s",machine); 61 engOutputBuffer(e->ep,e->buffer,1024); 62 63 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 64 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 65 sprintf(buffer,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size); 66 engEvalString(e->ep, buffer); 67 ierr = PetscInfo1(0,"Started MATLAB engine on %s\n",machine);CHKERRQ(ierr); 68 69 *mengine = e; 70 PetscFunctionReturn(0); 71 } 72 73 /*@ 74 PetscMatlabEngineDestroy - Destroys a vector. 75 76 Collective on PetscMatlabEngine 77 78 Input Parameters: 79 . e - the engine 80 81 Level: advanced 82 83 .seealso: PetscMatlabEnginCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 84 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 85 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 86 @*/ 87 PetscErrorCode PetscMatlabEngineDestroy(PetscMatlabEngine *v) 88 { 89 PetscErrorCode ierr; 90 91 PetscFunctionBegin; 92 if (!*v) PetscFunctionReturn(0); 93 PetscValidHeaderSpecific(*v,MATLABENGINE_CLASSID,1); 94 if (--((PetscObject)(*v))->refct > 0) PetscFunctionReturn(0); 95 ierr = PetscHeaderDestroy(v);CHKERRQ(ierr); 96 PetscFunctionReturn(0); 97 } 98 99 /*@C 100 PetscMatlabEngineEvaluate - Evaluates a string in MATLAB 101 102 Not Collective 103 104 Input Parameters: 105 + mengine - the MATLAB engine 106 - string - format as in a printf() 107 108 Level: advanced 109 110 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 111 PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 112 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 113 @*/ 114 PetscErrorCode PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...) 115 { 116 va_list Argp; 117 char buffer[1024]; 118 PetscErrorCode ierr; 119 size_t fullLength; 120 121 PetscFunctionBegin; 122 va_start(Argp,string); 123 ierr = PetscVSNPrintf(buffer,1024-9-5,string,&fullLength,Argp);CHKERRQ(ierr); 124 va_end(Argp); 125 126 ierr = PetscInfo1(0,"Evaluating MATLAB string: %s\n",buffer);CHKERRQ(ierr); 127 engEvalString(mengine->ep, buffer); 128 129 /* 130 Check for error in MATLAB: indicated by ? as first character in engine->buffer 131 */ 132 if (mengine->buffer[4] == '?') SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in evaluating MATLAB command:%s\n%s",string,mengine->buffer); 133 134 ierr = PetscInfo1(0,"Done evaluating Matlab string: %s\n",buffer);CHKERRQ(ierr); 135 PetscFunctionReturn(0); 136 } 137 138 /*@C 139 PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is 140 printed 141 142 Not Collective 143 144 Input Parameter: 145 . mengine - the MATLAB engine 146 147 Output Parameter: 148 . string - buffer where MATLAB output is printed 149 150 Level: advanced 151 152 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 153 PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(), 154 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 155 @*/ 156 PetscErrorCode PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string) 157 { 158 PetscFunctionBegin; 159 *string = mengine->buffer; 160 PetscFunctionReturn(0); 161 } 162 163 /*@C 164 PetscMatlabEnginePrintOutput - prints the output from MATLAB 165 166 Collective on PetscMatlabEngine 167 168 Input Parameters: 169 . mengine - the Matlab engine 170 171 Level: advanced 172 173 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 174 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(), 175 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 176 @*/ 177 PetscErrorCode PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd) 178 { 179 PetscErrorCode ierr; 180 PetscMPIInt rank; 181 182 PetscFunctionBegin; 183 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);CHKERRQ(ierr); 184 ierr = PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);CHKERRQ(ierr); 185 ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine),fd);CHKERRQ(ierr); 186 PetscFunctionReturn(0); 187 } 188 189 /*@ 190 PetscMatlabEnginePut - Puts a Petsc object into the MATLAB space. For parallel objects, 191 each processors part is put in a separate MATLAB process. 192 193 Collective on PetscObject 194 195 Input Parameters: 196 + mengine - the MATLAB engine 197 - object - the PETSc object, for example Vec 198 199 Level: advanced 200 201 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(), 202 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 203 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine 204 @*/ 205 PetscErrorCode PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj) 206 { 207 PetscErrorCode ierr,(*put)(PetscObject,void*); 208 209 PetscFunctionBegin; 210 ierr = PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);CHKERRQ(ierr); 211 if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name); 212 ierr = PetscInfo(0,"Putting MATLAB object\n");CHKERRQ(ierr); 213 ierr = (*put)(obj,mengine->ep);CHKERRQ(ierr); 214 ierr = PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);CHKERRQ(ierr); 215 PetscFunctionReturn(0); 216 } 217 218 /*@ 219 PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object. 220 221 Collective on PetscObject 222 223 Input Parameters: 224 + mengine - the MATLAB engine 225 - object - the PETSc object, for example Vec 226 227 Level: advanced 228 229 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(), 230 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 231 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), MatlabEngineGetArray(), PetscMatlabEngine 232 @*/ 233 PetscErrorCode PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj) 234 { 235 PetscErrorCode ierr,(*get)(PetscObject,void*); 236 237 PetscFunctionBegin; 238 if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name"); 239 ierr = PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);CHKERRQ(ierr); 240 if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name); 241 ierr = PetscInfo(0,"Getting MATLAB object\n");CHKERRQ(ierr); 242 ierr = (*get)(obj,mengine->ep);CHKERRQ(ierr); 243 ierr = PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);CHKERRQ(ierr); 244 PetscFunctionReturn(0); 245 } 246 247 /* 248 The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that 249 is attached to a communicator, in this case the attribute is a PetscMatlabEngine 250 */ 251 static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID; 252 253 254 /*@C 255 PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors 256 in a communicator. 257 258 Not Collective 259 260 Input Parameter: 261 . comm - the MPI communicator to share the engine 262 263 Level: developer 264 265 Notes: 266 Unlike almost all other PETSc routines, this does not return 267 an error code. Usually used in the form 268 $ PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm)); 269 270 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 271 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 272 PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine, 273 PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF 274 275 @*/ 276 PetscMatlabEngine PETSC_MATLAB_ENGINE_(MPI_Comm comm) 277 { 278 PetscErrorCode ierr; 279 PetscBool flg; 280 PetscMatlabEngine mengine; 281 282 PetscFunctionBegin; 283 if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) { 284 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0); 285 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 286 } 287 ierr = MPI_Comm_get_attr(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg); 288 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 289 if (!flg) { /* viewer not yet created */ 290 char *machinename = 0,machine[64]; 291 292 ierr = PetscOptionsGetString(NULL,NULL,"-matlab_engine_machine",machine,64,&flg); 293 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 294 if (flg) machinename = machine; 295 ierr = PetscMatlabEngineCreate(comm,machinename,&mengine); 296 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 297 ierr = PetscObjectRegisterDestroy((PetscObject)mengine); 298 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 299 ierr = MPI_Comm_set_attr(comm,Petsc_Matlab_Engine_keyval,mengine); 300 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 301 } 302 PetscFunctionReturn(mengine); 303 } 304 305 /*@C 306 PetscMatlabEnginePutArray - Puts an array into the MATLAB space, treating it as a Fortran style (column major ordering) array. For parallel objects, 307 each processors part is put in a separate MATLAB process. 308 309 Collective on PetscObject 310 311 Input Parameters: 312 + mengine - the MATLAB engine 313 . m,n - the dimensions of the array 314 . array - the array (represented in one dimension) 315 - name - the name of the array 316 317 Level: advanced 318 319 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(), 320 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 321 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), MatlabEngineGetArray(), PetscMatlabEngine 322 @*/ 323 PetscErrorCode PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[]) 324 { 325 PetscErrorCode ierr; 326 mxArray *mat; 327 328 PetscFunctionBegin; 329 ierr = PetscInfo1(0,"Putting MATLAB array %s\n",name);CHKERRQ(ierr); 330 #if !defined(PETSC_USE_COMPLEX) 331 mat = mxCreateDoubleMatrix(m,n,mxREAL); 332 #else 333 mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX); 334 #endif 335 ierr = PetscMemcpy(mxGetPr(mat),array,m*n*sizeof(PetscScalar));CHKERRQ(ierr); 336 engPutVariable(mengine->ep,name,mat); 337 338 ierr = PetscInfo1(0,"Put MATLAB array %s\n",name);CHKERRQ(ierr); 339 PetscFunctionReturn(0); 340 } 341 342 /*@C 343 PetscMatlabEngineGetArray - Gets a variable from Matlab into an array 344 345 Not Collective 346 347 Input Parameters: 348 + mengine - the Matlab engine 349 . m,n - the dimensions of the array 350 . array - the array (represented in one dimension) 351 - name - the name of the array 352 353 Level: advanced 354 355 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(), 356 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 357 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine 358 @*/ 359 PetscErrorCode PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[]) 360 { 361 PetscErrorCode ierr; 362 mxArray *mat; 363 364 PetscFunctionBegin; 365 ierr = PetscInfo1(0,"Getting MATLAB array %s\n",name);CHKERRQ(ierr); 366 mat = engGetVariable(mengine->ep,name); 367 if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name); 368 ierr = PetscMemcpy(array,mxGetPr(mat),m*n*sizeof(PetscScalar));CHKERRQ(ierr); 369 ierr = PetscInfo1(0,"Got MATLAB array %s\n",name);CHKERRQ(ierr); 370 PetscFunctionReturn(0); 371 } 372 373 374 375 376