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