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