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